大家好。我试图通过静态缓存和重用编译查询来优化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个人。是否有可能提取出以这种方式接受参数的子句?
查看谓词生成器。医生都很好。
我已经使用它来支持几十个谓词,结果代码在经过良好分解后非常小。