c# - Using a local variable in an expression tree -


i have linq expression finds historical changes given customer's creditbalance:

var history = gethistory(id); var changes = history.where(x => history.where(y => y.auditid < x.auditid)                                         .orderbydescending(y => y.auditid)                                         .select(y => y.creditbalance)                                         .firstordefault() != x.creditbalance); 

this function works expected. want change function allow user query changes any historical field. way chose tackle expression trees.

so far have come solution:

var history = gethistory(id); var c = expression.parameter(typeof(customer_history), "c"); var d = expression.parameter(typeof(customer_history), "d"); var caudit = expression.property(c, typeof(customer_history).getproperty("auditid")); var daudit = expression.property(d, typeof(customer_history).getproperty("auditid"));  var wherebody = expression.lessthan(daudit, caudit); var wherelambda = expression.lambda(wherebody, d); var = methods.queryablewhere.makegenericmethod(typeof(customer_history));  var wherecall = expression.call(null, where, **expression.constant(history)**, wherelambda);  var orderbylambda = expression.lambda(daudit, d);  var orderby = methods.queryableorderbydescending.makegenericmethod(typeof(customer_history), orderbylambda.body.type); var orderbycall = expression.call(null, orderby, wherecall, orderbylambda);  var dprop = expression.property(d, typeof(customer_history).getproperty(field)); var selectlambda = expression.lambda(dprop, d);  var select = methods.queryableselect.makegenericmethod(typeof(customer_history), selectlambda.body.type); var selectcall = expression.call(null, select, orderbycall, selectlambda);  var firstordefault = methods.queryablefirstordefault.makegenericmethod(selectlambda.body.type); var firstordefaultcall = expression.call(null, firstordefault, selectcall);  var cprop = expression.property(c, typeof(customer_history).getproperty(field)); var comparison = expression.notequal(firstordefaultcall, cprop); var lambda = expression.lambda<func<customer_history, bool>>(comparison, c);  var changes = history.where(lambda); 

the problem is, exception when query executed:

unable create constant value of type 'namespace.customer_history'. primitive types or enumeration types supported in context.

now assuming issue expression.constant(history) statement based on exception message. problem is, don't know how rewrite allow query provider handle appropriately. know works because of original query, don't know how in expression tree.

can provide direction?

as suspected, seems constantexpression not way obtain value local variable.

what needed create private class store variable in, , able access field memberexpression

private class valueholder<t> {       public iqueryable<t> history; } 

then in method able have expression evaluated using this:

var valueholder = new valueholder<t> {       history = data };  var c = expression.parameter(typeof(t), "c"); var constantex = expression.constant(valueholder); var fieldex = expression.field(constantex, valueholder.gettype().getfield("history")); 

Comments

Popular posts from this blog

java - Intellij Synchronizing output directories .. -

git - Initial Commit: "fatal: could not create leading directories of ..." -