c# - Type error trying to call Any() using Expression<Func<..>> from method -
i creating reusable mapping expression ef entity bll entity:
private expression<func<person, bool>> getnamefilter(string name) { return person => person.profile.username == name; } internal expression<func<ef.perk, bll.perk>> mapperkperk(string name) { return perk => new bll.perk { id = perk.perkid, name = perk.perkname, description = perk.perkdescription, //compilation error owned = perk.players.any(getnamefilter(name)) }; }
and getting compilation error on noted line. error reads:
icollection not contain definition 'any' , best extension method overload 'queryable.any(iqueryable, expression>)' requires receiver of type 'iqueryable'
but not happen when push expression in directly:
internal expression<func<ef.perk, bll.perk>> mapperkperk(string name) { return perk => new bll.perk { id = perk.perkid, name = perk.perkname, description = perk.perkdescription, //no compilation error owned = perk.players.any(person => person.profile.username == name) }; }
why happening? type of both expressions same.
using linqexpression solution found below, getting following error @ runtime:
an exception of type 'system.invalidcastexception' occurred in linqkit.dll not handled in user code
additional information: unable cast object of type 'system.linq.expressions.instancemethodcallexpressionn' type 'system.linq.expressions.lambdaexpression'.
internal futurequery<perk> getplayerinfoperks(string username) { return master .perks .visibleperks .select(master.perks.mapperkperk(username)) .future(); }
is due use of entityframework.future library?
why happening? type of both expressions same.
the type of both expressions not same - visually same. following valid:
dbcontext.persons.any(getnamefilter(name))
and not:
perk.players.any(getnamefilter(name))
why? because first expects expression<func<...>>
while second - func<..>
(the typical difference between iqueryable<t>
, ienumerable<t>
methods same name). hope see difference. when type directly, c# compiler magic emit 1 or another, when manually, supposed use correct one.
the problem addressed linqkit package invoke
/ expand
custom extension methods (and more asexpandable
).
for concrete example, linqkit solution this:
using linqkit; ... internal expression<func<ef.perk, bll.perk>> mapperkperk(string name) { // linqkit requires expressions in variables var namefilter = getnamefilter(name); return linq.expr((ef.perk perk) => new bll.perk { id = perk.perkid, name = perk.perkname, description = perk.perkdescription, owned = perk.players.any(p => namefilter.invoke(p)) }).expand(); }
Comments
Post a Comment