Beispiel #1
0
        public static Expression Create(
            Type type,
            Expression keyExpression,
            EnumerableRelationalQueryExpression elementsExpression)
        {
            if (type.IsGenericType(typeof(IGrouping <,>)))
            {
                var expandedGroupingType
                    = typeof(ExpandedGrouping <,>)
                      .MakeGenericType(type.GenericTypeArguments);

                return(Expression.New(
                           expandedGroupingType.GetTypeInfo().DeclaredConstructors.Single(),
                           new[] { keyExpression, elementsExpression },
                           new[]
                {
                    expandedGroupingType.GetRuntimeProperty("Key"),
                    expandedGroupingType.GetRuntimeProperty("Elements")
                }));
            }
            else
            {
                return(elementsExpression);
            }
        }
Beispiel #2
0
        public override Expression Visit(Expression node)
        {
            var visited = base.Visit(node);

            switch (visited)
            {
            case GroupByResultExpression groupByResultExpression:
            {
                var uniquifier = new TableUniquifyingExpressionVisitor();

                var oldSelectExpression = groupByResultExpression.SelectExpression;
                var newSelectExpression = uniquifier.VisitAndConvert(oldSelectExpression, nameof(VisitMethodCall));

                var oldTables = oldSelectExpression.Table.Flatten().ToArray();
                var newTables = newSelectExpression.Table.Flatten().ToArray();

                var updater = new TableUpdatingExpressionVisitor(oldTables, newTables);

                var outerKeySelector = groupByResultExpression.OuterKeySelector;
                var innerKeySelector = updater.Visit(groupByResultExpression.InnerKeySelector);
                var elementSelector  = updater.Visit(groupByResultExpression.ElementSelector);

                var elements
                    = new EnumerableRelationalQueryExpression(
                          newSelectExpression
                          .UpdateProjection(new ServerProjectionExpression(elementSelector))
                          .AddToPredicate(Expression.Equal(outerKeySelector, innerKeySelector)));

                return(ExpandGroup(visited, outerKeySelector, elements));
            }

            case GroupedRelationalQueryExpression groupedRelationalQueryExpression:
            {
                var outerKeySelector = groupedRelationalQueryExpression.OuterKeySelector;
                var innerKeySelector = groupedRelationalQueryExpression.InnerKeySelector;

                if (groupedRelationalQueryExpression.RequiresDenullification)
                {
                    outerKeySelector = JoinKeyDenullifyingExpressionVisitor.Instance.Visit(outerKeySelector);
                    innerKeySelector = JoinKeyDenullifyingExpressionVisitor.Instance.Visit(innerKeySelector);
                }

                var elements
                    = new EnumerableRelationalQueryExpression(
                          groupedRelationalQueryExpression.SelectExpression
                          .AddToPredicate(
                              Expression.Equal(
                                  outerKeySelector,
                                  innerKeySelector)));

                return(ExpandGroup(visited, groupedRelationalQueryExpression.OuterKeySelector, elements));
            }

            default:
            {
                return(visited);
            }
            }
        }
Beispiel #3
0
        public override Expression Visit(Expression node)
        {
            var visited = base.Visit(node);

            switch (visited)
            {
            case GroupByResultExpression groupByResultExpression:
            {
                var uniquifier = new TableUniquifyingExpressionVisitor();

                var oldSelectExpression = groupByResultExpression.SelectExpression;
                var newSelectExpression = uniquifier.VisitAndConvert(oldSelectExpression, nameof(VisitMethodCall));

                var oldTables = oldSelectExpression.Table.Flatten().ToArray();
                var newTables = newSelectExpression.Table.Flatten().ToArray();

                var updater = new TableUpdatingExpressionVisitor(oldTables, newTables);

                var outerKeySelector = groupByResultExpression.OuterKeySelector;
                var innerKeySelector = updater.Visit(groupByResultExpression.InnerKeySelector);
                var elementSelector  = updater.Visit(groupByResultExpression.ElementSelector);

                if (IsTranslatable(outerKeySelector) && IsTranslatable(innerKeySelector) && IsTranslatable(elementSelector))
                {
                    var projection
                        = elementSelector
                          .VisitWith(postExpansionVisitors);

                    var predicate
                        = Expression
                          .Equal(outerKeySelector, innerKeySelector)
                          .VisitWith(postExpansionVisitors);

                    var query
                        = new EnumerableRelationalQueryExpression(
                              newSelectExpression
                              .UpdateProjection(new ServerProjectionExpression(projection))
                              .AddToPredicate(predicate));

                    return(ExpandedGrouping.Create(
                               groupByResultExpression.Type,
                               groupByResultExpression.OuterKeySelector,
                               query.AsList()));
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            case GroupedRelationalQueryExpression groupedRelationalQueryExpression:
            {
                var outerKeySelector = groupedRelationalQueryExpression.OuterKeySelector;
                var innerKeySelector = groupedRelationalQueryExpression.InnerKeySelector;

                if (IsTranslatable(outerKeySelector) && IsTranslatable(innerKeySelector))
                {
                    if (groupedRelationalQueryExpression.RequiresDenullification)
                    {
                        outerKeySelector = JoinKeyDenullifyingExpressionVisitor.Instance.Visit(outerKeySelector);
                        innerKeySelector = JoinKeyDenullifyingExpressionVisitor.Instance.Visit(innerKeySelector);
                    }

                    var predicate
                        = Expression
                          .Equal(outerKeySelector, innerKeySelector)
                          .VisitWith(postExpansionVisitors);

                    var query
                        = new EnumerableRelationalQueryExpression(
                              groupedRelationalQueryExpression.SelectExpression
                              .AddToPredicate(predicate));

                    return(ExpandedGrouping.Create(
                               groupedRelationalQueryExpression.Type,
                               groupedRelationalQueryExpression.OuterKeySelector,
                               query.AsList()));
                }
                else
                {
                    var predicate
                        = Expression.Lambda(
                              Expression.Equal(
                                  outerKeySelector,
                                  groupedRelationalQueryExpression.InnerKeyLambda.Body),
                              groupedRelationalQueryExpression.InnerKeyLambda.Parameters);

                    return(Expression.Call(
                               queryableWhere.MakeGenericMethod(groupedRelationalQueryExpression.Type.GetSequenceType()),
                               new EnumerableRelationalQueryExpression(groupedRelationalQueryExpression.SelectExpression),
                               Expression.Quote(predicate)));
                }
            }

            default:
            {
                return(visited);
            }
            }
        }
Beispiel #4
0
        public Expression CreateQueryExpression(Type elementType, DbContext context)
        {
            var targetType = context.Model.GetEntityTypes().SingleOrDefault(t => t.ClrType == elementType);

            Expression queryExpression;

            if (targetType.DefiningQuery != null)
            {
                queryExpression = targetType.DefiningQuery.Body;

                goto ApplyQueryFilters;
            }

            var rootType = targetType.RootType();

            var schemaName = rootType.Relational().Schema ?? context.Model.Relational().DefaultSchema;
            var tableName  = rootType.Relational().TableName;

            var table
                = new BaseTableExpression(
                      schemaName,
                      tableName,
                      tableName.Substring(0, 1).ToLower(),
                      rootType.ClrType);

            var materializer = CreateMaterializer(targetType, table);

            var projection = new ServerProjectionExpression(materializer);

            var selectExpression = new SelectExpression(projection, table);

            var discriminatingType = targetType;

            while (discriminatingType != null)
            {
                var discriminatorProperty = discriminatingType.Relational().DiscriminatorProperty;

                if (discriminatorProperty != null)
                {
                    selectExpression
                        = selectExpression.AddToPredicate(
                              new SqlInExpression(
                                  MakeColumnExpression(
                                      table,
                                      discriminatorProperty),
                                  Expression.NewArrayInit(
                                      discriminatorProperty.ClrType,
                                      from t in discriminatingType.GetDerivedTypesInclusive()
                                      where !t.IsAbstract()
                                      select Expression.Constant(
                                          t.Relational().DiscriminatorValue,
                                          discriminatorProperty.ClrType))));
                }

                discriminatingType = FindSameTabledPrincipalType(discriminatingType);
            }

            queryExpression = new EnumerableRelationalQueryExpression(selectExpression);

ApplyQueryFilters:

            var currentType = targetType;
            var recast = false;

            while (currentType != null)
            {
                if (currentType.QueryFilter != null)
                {
                    var filterBody = currentType.QueryFilter.Body;

                    var repointer
                        = new QueryFilterRepointingExpressionVisitor(
                              DbContextParameter.GetInstance(context.GetType()));

                    filterBody = repointer.Visit(filterBody);

                    // Use a method call instead of adding to the SelectExpression
                    // so the rewriting visitors are guaranteed to get their hands on the
                    // filter.
                    queryExpression
                        = Expression.Call(
                              queryableWhereMethodInfo.MakeGenericMethod(currentType.ClrType),
                              queryExpression,
                              Expression.Quote(
                                  Expression.Lambda(
                                      new QueryFilterExpression(filterBody),
                                      currentType.QueryFilter.Parameters)));

                    recast |= currentType != targetType;
                }

                currentType = currentType.BaseType;
            }

            if (recast)
            {
                queryExpression
                    = Expression.Call(
                          queryableCastMethodInfo.MakeGenericMethod(targetType.ClrType),
                          queryExpression);
            }

            return(queryExpression);
        }