예제 #1
0
        IBuildContext ApplyQueryFilters(ExpressionBuilder builder, BuildInfo buildInfo, MemberInfo?memberInfo, TableContext tableContext)
        {
            var entityType = tableContext.ObjectType;

            if (builder.IsFilterDisabled(entityType))
            {
                return(tableContext);
            }

            var ed         = builder.MappingSchema.GetEntityDescriptor(entityType);
            var filterFunc = ed.QueryFilterFunc;

            if (filterFunc == null)
            {
                return(tableContext);
            }

            if (memberInfo == null)
            {
                memberInfo = Methods.LinqToDB.GetTable.MakeGenericMethod(entityType);
            }

            var fakeQuery = ExpressionQueryImpl.CreateQuery(entityType, builder.DataContext, null);

            // Here we tell for Equality Comparer to compare optimized expressions
            //
            builder.AddQueryableMemberAccessors((filterFunc, fakeQuery), new AccessorMember(memberInfo), builder.DataContext, static (context, mi, dc) =>
예제 #2
0
        IBuildContext ApplyQueryFilters(ExpressionBuilder builder, BuildInfo buildInfo, MemberInfo?memberInfo, TableContext tableContext)
        {
            var entityType = tableContext.ObjectType;

            if (builder.IsFilterDisabled(entityType))
            {
                return(tableContext);
            }

            var ed         = builder.MappingSchema.GetEntityDescriptor(entityType);
            var filterFunc = ed.QueryFilterFunc;

            if (filterFunc == null)
            {
                return(tableContext);
            }

            if (memberInfo == null)
            {
                memberInfo = Methods.LinqToDB.GetTable.MakeGenericMethod(entityType);
            }

            var fakeQuery = ExpressionQueryImpl.CreateQuery(entityType, builder.DataContext, null);

            // Here we tell for Equality Comparer to compare optimized expressions
            //
            var closureMappingSchema = builder.MappingSchema;

            builder.AddQueryableMemberAccessors(memberInfo, mi =>
            {
                var filtered = (IQueryable)filterFunc.DynamicInvoke(fakeQuery, builder.DataContext);

                // here we use light version of optimization, only for comparing trees
                var optimizationContext = new ExpressionTreeOptimizationContext(closureMappingSchema);
                var optimizedExpr       = optimizationContext.ExposeExpression(filtered.Expression);
                optimizedExpr           = optimizationContext.ExpandQueryableMethods(optimizedExpr);
                optimizedExpr           = optimizedExpr.OptimizeExpression() !;
                return(optimizedExpr);
            });

            var filtered  = (IQueryable)filterFunc.DynamicInvoke(fakeQuery, builder.DataContext);
            var optimized = filtered.Expression;

            optimized = builder.ConvertExpressionTree(optimized);
            optimized = builder.ConvertExpression(optimized);
            optimized = optimized.OptimizeExpression() !;

            var refExpression = new ContextRefExpression(typeof(IQueryable <>).MakeGenericType(entityType), tableContext);
            var replaced      = optimized.Replace(fakeQuery.Expression, refExpression);

            if (replaced == optimized)
            {
                throw new LinqException("Could not correct query result for processing.");
            }

            var context = builder.BuildSequence(new BuildInfo(buildInfo, replaced));

            return(context);
        }