Пример #1
0
 public virtual ISqlQueryGenerator CreateGenerator()
 => _sqlQueryGeneratorFactory.CreateGenerator(this);
Пример #2
0
        private IEnumerable <Expression> CreateIncludeRelatedValuesStrategyFactories(
            IQuerySource querySource,
            IEnumerable <INavigation> navigationPath)
        {
            var selectExpression
                = _queryCompilationContext.FindSelectExpression(querySource);

            var targetTableExpression
                = selectExpression.GetTableForQuerySource(querySource);

            var canProduceInnerJoin = true;
            var navigationCount     = 0;

            foreach (var navigation in navigationPath)
            {
                var queryIndex = _queryIndexes[navigationCount];
                navigationCount++;

                var targetEntityType = navigation.GetTargetType();
                var targetTableName  = _relationalAnnotationProvider.For(targetEntityType).TableName;
                var targetTableAlias = targetTableName[0].ToString().ToLower();

                if (!navigation.IsCollection())
                {
                    var joinedTableExpression
                        = new TableExpression(
                              targetTableName,
                              _relationalAnnotationProvider.For(targetEntityType).Schema,
                              targetTableAlias,
                              querySource);

                    var valueBufferOffset = selectExpression.Projection.Count;

                    canProduceInnerJoin
                        = canProduceInnerJoin &&
                          (navigation.ForeignKey.IsRequired &&
                           navigation.PointsToPrincipal());

                    var joinExpression
                        = canProduceInnerJoin
                            ? selectExpression
                          .AddInnerJoin(joinedTableExpression)
                            : selectExpression
                          .AddOuterJoin(joinedTableExpression);

                    var oldPredicate = selectExpression.Predicate;

                    var materializer
                        = _materializerFactory
                          .CreateMaterializer(
                              targetEntityType,
                              selectExpression,
                              (p, se) => se.AddToProjection(
                                  new AliasExpression(
                                      new ColumnExpression(
                                          _relationalAnnotationProvider.For(p).ColumnName,
                                          p,
                                          joinedTableExpression))) - valueBufferOffset,
                              querySource: null);

                    if (selectExpression.Predicate != oldPredicate)
                    {
                        var newJoinExpression = AdjustJoinExpression(selectExpression, joinExpression);

                        selectExpression.Predicate = oldPredicate;
                        selectExpression.RemoveTable(joinExpression);
                        selectExpression.AddTable(newJoinExpression);
                        joinExpression = newJoinExpression;
                    }

                    joinExpression.Predicate
                        = BuildJoinEqualityExpression(
                              navigation,
                              navigation.PointsToPrincipal() ? targetTableExpression : joinExpression,
                              navigation.PointsToPrincipal() ? joinExpression : targetTableExpression,
                              querySource);

                    targetTableExpression = joinedTableExpression;

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

                    foreach (var property in navigation.ForeignKey.PrincipalKey.Properties)
                    {
                        selectExpression
                        .AddToOrderBy(
                            _relationalAnnotationProvider.For(property).ColumnName,
                            property,
                            principalTable,
                            OrderingDirection.Asc);
                    }

                    var targetSelectExpression = _selectExpressionFactory.Create();

                    targetTableExpression
                        = new TableExpression(
                              targetTableName,
                              _relationalAnnotationProvider.For(targetEntityType).Schema,
                              targetTableAlias,
                              querySource);

                    targetSelectExpression.AddTable(targetTableExpression);

                    var materializer
                        = _materializerFactory
                          .CreateMaterializer(
                              targetEntityType,
                              targetSelectExpression,
                              (p, se) => se.AddToProjection(
                                  _relationalAnnotationProvider.For(p).ColumnName,
                                  p,
                                  querySource),
                              querySource: null);

                    var innerJoinSelectExpression
                        = selectExpression.Clone(
                              selectExpression.OrderBy
                              .Select(o => o.Expression)
                              .Last(o => o.IsAliasWithColumnExpression())
                              .TryGetColumnExpression().TableAlias);

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

                    var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression);

                    LiftOrderBy(innerJoinSelectExpression, targetSelectExpression, innerJoinExpression);

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

                    selectExpression = targetSelectExpression;

                    yield return
                        (Expression.Lambda(
                             Expression.Call(
                                 _queryCompilationContext.QueryMethodProvider
                                 .CreateCollectionIncludeRelatedValuesStrategyMethod,
                                 Expression.Call(
                                     _queryCompilationContext.QueryMethodProvider.QueryMethod,
                                     EntityQueryModelVisitor.QueryContextParameter,
                                     Expression.Constant(
                                         _commandBuilderFactory.Create(
                                             () => _sqlQueryGeneratorFactory
                                             .CreateGenerator(targetSelectExpression))),
                                     Expression.Constant(_queryCompilationContext.Logger),
                                     Expression.Constant(queryIndex, typeof(int?))),
                                 materializer)));
                }
            }
        }