Пример #1
0
        protected override Expression InlineQueryable(IQueryable queryable)
        {
            if (queryable.Expression.Type.IsGenericType(typeof(EntityQueryable <>)))
            {
                var key = queryable.ElementType.TypeHandle.Value;

                var query
                    = modelQueryExpressionCache.Lookup.GetOrAdd(
                          key,
                          (k, arg) =>
                          arg.modelExpressionProvider.CreateQueryExpression(
                              arg.queryable.ElementType,
                              arg.currentDbContext.Context),
                          (modelExpressionProvider, queryable, currentDbContext));

                // This block is moreso for types with defining queries than types that
                // just happen to have query filters. The defining queries need to be inlined.

                if (!(query is RelationalQueryExpression))
                {
                    var repointer = new QueryFilterRepointingExpressionVisitor(dbContextParameter);

                    var repointed = repointer.Visit(query);

                    query = Visit(Reparameterize(repointed));
                }

                return(query);
            }

            return(base.InlineQueryable(queryable));
        }
        protected override Expression InlineQueryable(IQueryable queryable)
        {
            if (queryable.Expression.Type.IsGenericType(typeof(EntityQueryable <>)))
            {
                var key = queryable.ElementType.TypeHandle.Value;

                if (!modelQueryExpressionCache.Lookup.TryGetValue(key, out var query))
                {
                    query
                        = modelExpressionProvider.CreateQueryExpression(
                              queryable.ElementType,
                              currentDbContext.Context);

                    modelQueryExpressionCache.Lookup[key] = query;
                }

                // This block is moreso for types with defining queries than types that
                // just happen to have query filters. The defining queries need to be inlined.

                if (!(query is RelationalQueryExpression))
                {
                    var repointer = new QueryFilterRepointingExpressionVisitor(dbContextParameter);

                    var repointed = repointer.Visit(query);

                    query = Visit(Reparameterize(repointed));
                }

                // TODO: Should be able to get rid of this block

                if (queryable.ElementType != query.Type.GetSequenceType())
                {
                    query
                        = Expression.Call(
                              typeof(Queryable)
                              .GetMethod(nameof(Queryable.Cast))
                              .MakeGenericMethod(queryable.ElementType),
                              query);
                }

                return(query);
            }

            return(base.InlineQueryable(queryable));
        }
Пример #3
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);
        }