示例#1
0
        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);
示例#5
0
        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)));
        }