private void Include( object entity, IReadOnlyList <INavigation> navigationPath, IReadOnlyList <RelatedEntitiesLoader> relatedEntitiesLoaders, int currentNavigationIndex, bool queryStateManager) { if (entity == null || currentNavigationIndex == navigationPath.Count) { return; } IKeyValue primaryKeyValue; Func <ValueBuffer, IKeyValue> relatedKeyFactory; var targetEntityType = IncludeCore( entity, navigationPath[currentNavigationIndex], out primaryKeyValue, out relatedKeyFactory); var keyValueFactory = _keyValueFactorySource .GetKeyFactory(targetEntityType.FindPrimaryKey()); LoadNavigationProperties( entity, navigationPath, currentNavigationIndex, relatedEntitiesLoaders[currentNavigationIndex](primaryKeyValue, relatedKeyFactory) .Select(eli => { var keyValue = keyValueFactory.Create(eli.ValueBuffer); object targetEntity = null; if (!ReferenceEquals(keyValue, KeyValue.InvalidKeyValue)) { targetEntity = GetEntity(keyValue, eli, queryStateManager); } Include( targetEntity, navigationPath, relatedEntitiesLoaders, currentNavigationIndex + 1, queryStateManager); return(targetEntity); }) .Where(e => e != null) .ToList()); }
protected override Expression VisitEntityQueryable(Type elementType) { Check.NotNull(elementType, nameof(elementType)); var entityType = _model.FindEntityType(elementType); if (QueryModelVisitor.QueryCompilationContext .QuerySourceRequiresMaterialization(_querySource)) { var materializer = _materializerFactory.CreateMaterializer(entityType); return(Expression.Call( InMemoryQueryModelVisitor.EntityQueryMethodInfo.MakeGenericMethod(elementType), EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(entityType), Expression.Constant(_keyValueFactorySource.GetKeyFactory(entityType.FindPrimaryKey())), materializer, Expression.Constant(QueryModelVisitor.QueryCompilationContext.IsTrackingQuery))); } return(Expression.Call( InMemoryQueryModelVisitor.ProjectionQueryMethodInfo, EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(entityType))); }
public EntityTrackingInfo( [NotNull] IKeyValueFactorySource keyValueFactorySource, [NotNull] QueryCompilationContext queryCompilationContext, [NotNull] QuerySourceReferenceExpression querySourceReferenceExpression, [NotNull] IEntityType entityType) { Check.NotNull(keyValueFactorySource, nameof(keyValueFactorySource)); Check.NotNull(querySourceReferenceExpression, nameof(querySourceReferenceExpression)); Check.NotNull(entityType, nameof(entityType)); Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); QuerySourceReferenceExpression = querySourceReferenceExpression; _entityType = entityType; _keyValueFactory = keyValueFactorySource.GetKeyFactory(_entityType.FindPrimaryKey()); _includedNavigationPaths = queryCompilationContext .GetTrackableIncludes(querySourceReferenceExpression.ReferencedQuerySource); if (_includedNavigationPaths != null) { _includedEntityTrackingInfos = new Dictionary <INavigation, IncludedEntityTrackingInfo>(); foreach (var navigation in _includedNavigationPaths.SelectMany(ns => ns)) { if (!_includedEntityTrackingInfos.ContainsKey(navigation)) { var targetEntityType = navigation.GetTargetType(); _includedEntityTrackingInfos.Add( navigation, new IncludedEntityTrackingInfo( targetEntityType, keyValueFactorySource.GetKeyFactory(targetEntityType.FindPrimaryKey()))); } } } }
public virtual IKeyValue CreateKey(IKey key, IReadOnlyList <IProperty> properties, IPropertyAccessor propertyAccessor) => _keyValueFactorySource .GetKeyFactory(key) .Create(properties, propertyAccessor);
protected override Expression VisitEntityQueryable(Type elementType) { Check.NotNull(elementType, nameof(elementType)); var queryMethodInfo = CreateValueBufferMethodInfo; var relationalQueryCompilationContext = QueryModelVisitor.QueryCompilationContext; var entityType = _model.FindEntityType(elementType); var selectExpression = _selectExpressionFactory.Create(); var name = _relationalAnnotationProvider.For(entityType).TableName; var tableAlias = _querySource.HasGeneratedItemName() ? name[0].ToString().ToLowerInvariant() : _querySource.ItemName; var fromSqlAnnotation = relationalQueryCompilationContext .GetCustomQueryAnnotations(RelationalQueryableExtensions.FromSqlMethodInfo) .LastOrDefault(a => a.QuerySource == _querySource); var composable = true; var sqlString = ""; object[] sqlParameters = null; if (fromSqlAnnotation == null) { selectExpression.AddTable( new TableExpression( name, _relationalAnnotationProvider.For(entityType).Schema, tableAlias, _querySource)); } else { sqlString = (string)fromSqlAnnotation.Arguments[1]; sqlParameters = (object[])fromSqlAnnotation.Arguments[2]; selectExpression.AddTable( new RawSqlDerivedTableExpression( sqlString, sqlParameters, tableAlias, _querySource)); var sqlStart = sqlString.SkipWhile(char.IsWhiteSpace).Take(7).ToArray(); if (sqlStart.Length != 7 || !char.IsWhiteSpace(sqlStart.Last()) || !new string(sqlStart).StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)) { if (relationalQueryCompilationContext.QueryAnnotations .OfType <IncludeQueryAnnotation>().Any()) { throw new InvalidOperationException(RelationalStrings.StoredProcedureIncludeNotSupported); } QueryModelVisitor.RequiresClientEval = true; composable = false; } if (fromSqlAnnotation.QueryModel.IsIdentityQuery() && !fromSqlAnnotation.QueryModel.ResultOperators.Any()) { composable = false; } } QueryModelVisitor.AddQuery(_querySource, selectExpression); var queryMethodArguments = new List <Expression> { Expression.Constant(_querySource), _valueBufferParameter, Expression.Constant(0) }; if (QueryModelVisitor.QueryCompilationContext .QuerySourceRequiresMaterialization(_querySource) || QueryModelVisitor.RequiresClientEval) { var materializer = _materializerFactory .CreateMaterializer( entityType, selectExpression, (p, se) => se.AddToProjection( _relationalAnnotationProvider.For(p).ColumnName, p, _querySource), _querySource); queryMethodInfo = CreateEntityMethodInfo.MakeGenericMethod(elementType); queryMethodArguments.AddRange( new[] { EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(entityType), Expression.Constant(QueryModelVisitor.QueryCompilationContext.IsTrackingQuery), Expression.Constant(_keyValueFactorySource.GetKeyFactory(entityType.FindPrimaryKey())), materializer, Expression.Constant(false), Expression.Constant(QueryModelVisitor.QueryCompilationContext.IsQueryBufferRequired) }); } Func <ISqlQueryGenerator> sqlQueryGeneratorFunc; if (composable) { sqlQueryGeneratorFunc = selectExpression.CreateGenerator; } else { sqlQueryGeneratorFunc = () => selectExpression.CreateRawCommandGenerator( sqlString, sqlParameters); } return(Expression.Call( QueryModelVisitor.QueryCompilationContext.QueryMethodProvider // TODO: Don't use ShapedQuery when projecting .ShapedQueryMethod .MakeGenericMethod(queryMethodInfo.ReturnType), EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(_commandBuilderFactory.Create(sqlQueryGeneratorFunc)), Expression.Lambda( Expression.Call(queryMethodInfo, queryMethodArguments), _valueBufferParameter))); }