c# - How can I factor out clauses in a parameterized Expression? -
hey all. i'm trying optimize linq entities call statically caching , reusing compiled query. query checks same thing variable number of filter arguments, , way compile query arguments explicitly use number of arguments (rather contains()-type logic, in sql can't parameterized).
this works great , gives me major performance boost. problem code ugly. repeat same chunk of code number of times each of possible parameters. i.e:
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);
i thought i'd able refactor dynamically creating filter expressions, it's seeming impossible. want this:
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);
but of course won't compile because filterexpression expression , can't called (and can't func because linq entities won't recognize translatable method).
i can't capture parameters in closures outside expression, because if reuse compiled expression, values last call hard-coded , re-used. i.e., that's not parameterized query.
am stuck writing out whole thing every term? i'd support maximum of 14. possible factor out clauses take parameters in way?
check out predicate builder. docs pretty good.
i've used support dozens of predicates , resulting code small when well-factored.
Comments
Post a Comment