Ejemplo n.º 1
0
        internal static SelectExpression SelectAndFirstDatabaseExpressions(AdventureWorks adventureWorks)
        {
            QueryCompilationContext compilationContext = adventureWorks.GetService <IQueryCompilationContextFactory>()
                                                         .Create(async: false);
            SelectExpression selectExpression = new SelectExpression(
                dependencies: new SelectExpressionDependencies(adventureWorks.GetService <IQuerySqlGeneratorFactory>(), adventureWorks.GetService <IRelationalTypeMappingSource>()),
                queryCompilationContext: (RelationalQueryCompilationContext)compilationContext);
            MainFromClause querySource = new MainFromClause(
                itemName: "product",
                itemType: typeof(Product),
                fromExpression: Expression.Constant(adventureWorks.ProductCategories));
            TableExpression tableExpression = new TableExpression(
                table: nameof(Product),
                schema: AdventureWorks.Production,
                alias: querySource.ItemName,
                querySource: querySource);

            selectExpression.AddTable(tableExpression);
            IEntityType productEntityType = adventureWorks.Model.FindEntityType(typeof(Product));
            IProperty   nameProperty      = productEntityType.FindProperty(nameof(Product.Name));

            selectExpression.AddToProjection(new ColumnExpression(
                                                 name: nameof(Product.Name), property: nameProperty, tableExpression: tableExpression));
            selectExpression.Limit = Expression.Constant(1);
            return(selectExpression.WriteLine());
        }
        private JoinExpressionBase AdjustJoinExpression(
            SelectExpression selectExpression, JoinExpressionBase joinExpression)
        {
            var subquery
                = new SelectExpression(_querySqlGeneratorFactory, _queryCompilationContext)
                {
                Alias = joinExpression.Alias
                };

            // Don't create new alias when adding tables to subquery
            subquery.AddTable(joinExpression.TableExpression, createUniqueAlias: false);
            subquery.ProjectStarAlias = joinExpression.Alias;
            subquery.IsProjectStar    = true;
            subquery.Predicate        = selectExpression.Predicate;

            var newJoinExpression
                = joinExpression is LeftOuterJoinExpression
                    ? (JoinExpressionBase) new LeftOuterJoinExpression(subquery)
                    : new InnerJoinExpression(subquery);

            newJoinExpression.QuerySource = joinExpression.QuerySource;
            newJoinExpression.Alias       = joinExpression.Alias;

            return(newJoinExpression);
        }
            protected override Expression VisitEntityQueryable(Type elementType)
            {
                var relationalQueryCompilationContext = ((RelationalQueryCompilationContext)QueryCompilationContext);
                var queryMethodInfo = CreateValueReaderMethodInfo;
                var entityType      = QueryCompilationContext.Model.GetEntityType(elementType);

                var selectExpression = new SelectExpression();

                selectExpression
                .AddTable(
                    new TableExpression(
                        entityType.TableName(),
                        entityType.Schema(),
                        _querySource.ItemName.Replace("<generated>_", "t"),
                        _querySource));

                _queryModelVisitor._queriesBySource.Add(_querySource, selectExpression);

                var queryMethodArguments
                    = new List <Expression>
                    {
                    Expression.Constant(_querySource),
                    QueryContextParameter,
                    QuerySourceScopeParameter,
                    _readerParameter
                    };

                if (_queryModelVisitor.QuerySourceRequiresMaterialization(_querySource))
                {
                    foreach (var property in entityType.Properties)
                    {
                        selectExpression.AddToProjection(property, _querySource);
                    }

                    queryMethodInfo = CreateEntityMethodInfo.MakeGenericMethod(elementType);
                    queryMethodArguments.Add(Expression.Constant(0));
                }

                return(Expression.Call(
                           relationalQueryCompilationContext.QueryMethodProvider.QueryMethod
                           .MakeGenericMethod(queryMethodInfo.ReturnType),
                           QueryContextParameter,
                           Expression.Constant(new CommandBuilder(selectExpression, relationalQueryCompilationContext)),
                           Expression.Lambda(
                               Expression.Call(queryMethodInfo, queryMethodArguments),
                               _readerParameter)));
            }
Ejemplo n.º 4
0
        private IEnumerable <Expression> CreateIncludeRelatedValuesStrategyFactories(
            IQuerySource querySource,
            IEnumerable <INavigation> navigationPath)
        {
            var selectExpression
                = _queryCompilationContext.FindSelectExpression(querySource);

            var targetTableExpression
                = selectExpression.FindTableForQuerySource(querySource);

            var readerIndex = 0;

            foreach (var navigation in navigationPath)
            {
                if (!navigation.IsCollection())
                {
                    var targetEntityType = navigation.GetTargetType();
                    var targetTableName  = _queryCompilationContext.GetTableName(targetEntityType);
                    var targetTableAlias = targetTableName.First().ToString().ToLower();

                    var joinedTableExpression
                        = new TableExpression(
                              targetTableName,
                              _queryCompilationContext.GetSchema(targetEntityType),
                              targetTableAlias,
                              querySource);

                    var readerOffset = selectExpression.Projection.Count;

                    var columnExpressions
                        = targetEntityType.Properties
                          .Select(p => new ColumnExpression(
                                      _queryCompilationContext.GetColumnName(p),
                                      p,
                                      joinedTableExpression));

                    var joinExpression
                        = navigation.ForeignKey.IsRequired &&
                          navigation.PointsToPrincipal
                            ? selectExpression
                          .AddInnerJoin(joinedTableExpression, columnExpressions)
                            : selectExpression
                          .AddOuterJoin(joinedTableExpression, columnExpressions);

                    joinExpression.Predicate
                        = BuildJoinEqualityExpression(
                              navigation,
                              (navigation.PointsToPrincipal
                                ? targetEntityType
                                : navigation.EntityType)
                              .GetPrimaryKey().Properties,
                              navigation.PointsToPrincipal ? targetTableExpression : joinExpression,
                              navigation.PointsToPrincipal ? joinExpression : targetTableExpression);

                    targetTableExpression = joinedTableExpression;

                    yield return
                        (Expression.Lambda(
                             Expression.Call(
                                 _queryCompilationContext.QueryMethodProvider
                                 .CreateReferenceIncludeRelatedValuesStrategyMethod,
                                 Expression.Convert(EntityQueryModelVisitor.QueryContextParameter, typeof(RelationalQueryContext)),
                                 Expression.Constant(readerIndex),
                                 Expression.Constant(readerOffset))));
                }
                else
                {
                    var principalTable
                        = selectExpression.Tables.Last(t => t.QuerySource == querySource);

                    foreach (var property in navigation.EntityType.GetPrimaryKey().Properties)
                    {
                        selectExpression
                        .AddToOrderBy(
                            _queryCompilationContext.GetColumnName(property),
                            property,
                            principalTable,
                            OrderingDirection.Asc);
                    }

                    var targetEntityType = navigation.GetTargetType();
                    var targetTableName  = _queryCompilationContext.GetTableName(targetEntityType);
                    var targetTableAlias = targetTableName.First().ToString().ToLower();

                    var targetSelectExpression = new SelectExpression();

                    targetTableExpression
                        = new TableExpression(
                              targetTableName,
                              _queryCompilationContext.GetSchema(targetEntityType),
                              targetTableAlias,
                              querySource);

                    targetSelectExpression.AddTable(targetTableExpression);

                    foreach (var property in targetEntityType.Properties)
                    {
                        targetSelectExpression
                        .AddToProjection(
                            _queryCompilationContext.GetColumnName(property),
                            property,
                            querySource);
                    }

                    var innerJoinSelectExpression
                        = selectExpression.Clone(
                              ((ColumnExpression)selectExpression.OrderBy.Last().Expression).TableAlias);

                    innerJoinSelectExpression.IsDistinct = true;
                    innerJoinSelectExpression.ClearProjection();

                    foreach (var columnExpression
                             in innerJoinSelectExpression.OrderBy
                             .Select(o => o.Expression)
                             .Cast <ColumnExpression>())
                    {
                        innerJoinSelectExpression.AddToProjection(columnExpression);
                    }

                    innerJoinSelectExpression.ClearOrderBy();

                    var primaryKeyProperties = navigation.EntityType.GetPrimaryKey().Properties;

                    var innerJoinExpression
                        = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression);

                    foreach (var ordering in selectExpression.OrderBy)
                    {
                        var columnExpression = (ColumnExpression)ordering.Expression;

                        targetSelectExpression
                        .AddToOrderBy(
                            columnExpression.Name,
                            columnExpression.Property,
                            innerJoinExpression,
                            ordering.OrderingDirection);
                    }

                    innerJoinExpression.Predicate
                        = BuildJoinEqualityExpression(
                              navigation,
                              primaryKeyProperties,
                              targetTableExpression,
                              innerJoinExpression);

                    var readerParameter = Expression.Parameter(typeof(DbDataReader));

                    selectExpression = targetSelectExpression;
                    readerIndex++;

                    yield return
                        (Expression.Lambda(
                             Expression.Call(
                                 _queryCompilationContext.QueryMethodProvider
                                 .CreateCollectionIncludeRelatedValuesStrategyMethod,
                                 Expression.Call(
                                     _queryCompilationContext.QueryMethodProvider.QueryMethod
                                     .MakeGenericMethod(typeof(IValueReader)),
                                     EntityQueryModelVisitor.QueryContextParameter,
                                     Expression.Constant(new CommandBuilder(targetSelectExpression, _queryCompilationContext)),
                                     Expression.Lambda(
                                         Expression.Call(
                                             _createValueReaderForIncludeMethodInfo,
                                             EntityQueryModelVisitor.QueryContextParameter,
                                             readerParameter,
                                             Expression.Constant(targetEntityType)),
                                         readerParameter)))));
                }
            }
        }
        protected override Expression VisitEntityQueryable([NotNull] Type elementType)
        {
            Check.NotNull(elementType, nameof(elementType));

            var queryMethodInfo = RelationalQueryModelVisitor.CreateValueReaderMethodInfo;
            var entityType      = QueryModelVisitor.QueryCompilationContext.Model.GetEntityType(elementType);

            var selectExpression = new SelectExpression();
            var tableName        = QueryModelVisitor.QueryCompilationContext.GetTableName(entityType);

            var alias = _querySource.ItemName.StartsWith("<generated>_")
                ? tableName.First().ToString().ToLower()
                : _querySource.ItemName;

            var fromSqlAnnotation = GetAnnotations <FromSqlAnnotation>(_querySource).SingleOrDefault();

            selectExpression.AddTable(
                (fromSqlAnnotation != null)
                    ? (TableExpressionBase) new RawSqlDerivedTableExpression(
                    fromSqlAnnotation.Sql,
                    fromSqlAnnotation.Parameters,
                    alias,
                    _querySource)
                    : new TableExpression(
                    tableName,
                    QueryModelVisitor.QueryCompilationContext.GetSchema(entityType),
                    alias,
                    _querySource));

            QueryModelVisitor.AddQuery(_querySource, selectExpression);

            var queryMethodArguments
                = new List <Expression>
                {
                Expression.Constant(_querySource),
                EntityQueryModelVisitor.QueryContextParameter,
                EntityQueryModelVisitor.QuerySourceScopeParameter,
                _readerParameter
                };

            if (QueryModelVisitor.QuerySourceRequiresMaterialization(_querySource))
            {
                var materializer
                    = new MaterializerFactory(
                          QueryModelVisitor
                          .QueryCompilationContext
                          .EntityMaterializerSource)
                      .CreateMaterializer(
                          entityType,
                          selectExpression,
                          (p, se) =>
                          se.AddToProjection(
                              QueryModelVisitor.QueryCompilationContext.GetColumnName(p),
                              p,
                              _querySource),
                          _querySource);

                queryMethodInfo
                    = RelationalQueryModelVisitor.CreateEntityMethodInfo
                      .MakeGenericMethod(elementType);

                var keyProperties
                    = entityType.GetPrimaryKey().Properties;

                var keyFactory
                    = QueryModelVisitor.QueryCompilationContext.EntityKeyFactorySource
                      .GetKeyFactory(keyProperties);

                queryMethodArguments.AddRange(
                    new[]
                {
                    Expression.Constant(0),
                    Expression.Constant(entityType),
                    Expression.Constant(QueryModelVisitor.QuerySourceRequiresTracking(_querySource)),
                    Expression.Constant(keyFactory),
                    Expression.Constant(keyProperties),
                    materializer
                });
            }

            return(Expression.Call(
                       QueryModelVisitor.QueryCompilationContext.QueryMethodProvider.QueryMethod
                       .MakeGenericMethod(queryMethodInfo.ReturnType),
                       EntityQueryModelVisitor.QueryContextParameter,
                       Expression.Constant(new CommandBuilder(selectExpression, QueryModelVisitor.QueryCompilationContext)),
                       Expression.Lambda(
                           Expression.Call(queryMethodInfo, queryMethodArguments),
                           _readerParameter)));
        }