如何在参数化表达式中分解出子句



大家好。我试图通过静态缓存和重用编译查询来优化Linq对实体的调用。查询检查相同的事情,以检查过滤器参数的可变数量,编译查询参数的唯一方法是显式地使用多个参数(而不是一些Contains()类型的逻辑,后者在SQL中不能参数化)。

这很有效,给了我一个主要的性能提升。问题是代码很丑。对于每个可能的参数,我重复相同的代码块多次。即:

           Expression<Func<Entities, string, string, string, string, IQueryable<Instrument>>> query = 
(context, searchTerm0, searchTerm1, searchTerm2, searchTerm3) =>
                context.Instruments
                    .Where(
                        (searchTerm0 == null ||
                            instr.FullName.IndexOf(searchTerm0) > -1 ||
                            instr.ShortName.IndexOf(searchTerm0) > -1 ||
                            instr.Strategies.OrderBy(st => st.Level).Select(st => st.Name).Take(2).Any(strat => strat.IndexOf(searchTerm0) > -1))
                        &&
                        (searchTerm1 == null ||
                            instr.FullName.IndexOf(searchTerm1) > -1 ||
                            instr.ShortName.IndexOf(searchTerm1) > -1 ||
                            instr.Strategies.OrderBy(st => st.Level).Select(st => st.Name).Take(2).Any(strat => strat.IndexOf(searchTerm1) > -1))
                        &&
                        (searchTerm2 == null ||
                            instr.FullName.IndexOf(searchTerm2) > -1 ||
                            instr.ShortName.IndexOf(searchTerm2) > -1 ||
                            instr.Strategies.OrderBy(st => st.Level).Select(st => st.Name).Take(2).Any(strat => strat.IndexOf(searchTerm2) > -1))
                        &&
                        (searchTerm3 == null ||
                            instr.FullName.IndexOf(searchTerm3) > -1 ||
                            instr.ShortName.IndexOf(searchTerm3) > -1 ||
                            instr.Strategies.OrderBy(st => st.Level).Select(st => st.Name).Take(2).Any(strat => strat.IndexOf(searchTerm3) > -1))
                .Take(50);

我认为我可以通过动态创建过滤器表达式来重构它,但这似乎是不可能的。我想这样做:

    var filterExpression = (instr, searchTerm) =>
        searchTerm == null ||
        instr.FullName.IndexOf(searchTerm) > -1 ||
        instr.ShortName.IndexOf(searchTerm) > -1 ||
        instr.Strategies.OrderBy(st => st.Level).Select(st => st.Name).Take(2).Any(strat => strat.IndexOf(searchTerm) > -1);
    Expression<Func<Entities, string, string, string, string, IQueryable<Instrument>>> query = (context, searchTerm0, searchTerm1, searchTerm2, searchTerm3) =>
        context.Instruments
            .Where(i => filterExpression(i, searchTerm0))
            .Where(i => filterExpression(i, searchTerm1))
            .Where(i => filterExpression(i, searchTerm2))
            .Where(i => filterExpression(i, searchTerm3))
        .Take(50);

但是这当然不会编译,因为filterExpression是一个表达式,不能像那样调用(而且它不能只是一个Func,因为Linq to Entities不会将其识别为可翻译的方法)。

我也不能在表达式外的闭包中捕获参数,因为如果我重用编译后的表达式,最后调用的值将被硬编码并重用。也就是说,这不是一个参数化的查询。

我是不是要把每学期的全部内容都写出来?我想最多支持14个人。是否有可能提取出以这种方式接受参数的子句?

查看谓词生成器。医生都很好。

我已经使用它来支持几十个谓词,结果代码在经过良好分解后非常小。

相关内容

  • 没有找到相关文章