Reputation: 15159
I have a projection function that I pass to IQueryable<>.Select()
method:
private static Expression<Func<VendorPrice, PriceItem>> GetPriceSelector(){
return e => new PriceItem {
Id = e.Id,
Price = Math.Round(e.Price, 4)
};
}
Everything works just fine but I want to parameterize it like that:
private static Expression<Func<VendorPrice, PriceItem>> GetPriceSelector(Func<VendorPrice, decimal> formula){
return e => new PriceItem {
Id = e.Id,
Price = formula(e)
};
}
so that I can call it like
prices.Select(GetPriceSelector(e => Math.Round(e.Price, 4)))
Unfortunately, EF complains about it:
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities
How to rewrite the code to make EF happy?
Upvotes: 2
Views: 201
Reputation: 27871
First, the GetPriceSelector
method needs to take in an expression, not a function. The difference is that an expression is code as data so it can be translated to SQL, while a function is compiled code so it cannot be translated to SQL.
Next, you need a way to merge the two expressions. Doing this manually is hard. Fortunately, there is a library called LINQKit that can do that. Here is how you can solve your problem with LINQKit:
private static Expression<Func<VendorPrice, PriceItem>> GetPriceSelector(
Expression<Func<VendorPrice, decimal>> formula)
{
Expression<Func<VendorPrice, PriceItem>> expression = e => new PriceItem
{
Id = e.Id,
Price = formula.Invoke(e) //use the forumla expression here
};
return expression.Expand(); //This causes formula.Invoke(e) to be converted
//to something like Math.Round(e.Price, 4)
}
Upvotes: 2