예제 #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(new AccessorMember(memberInfo), builder.DataContext, (mi, dc) =>
            {
                var filtered = (IQueryable)filterFunc.DynamicInvoke(fakeQuery, dc) !;

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

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

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

            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);
        }