How to parameterize a selector with a function in EF query?

半腔热情 提交于 2019-12-06 11:07:36

问题


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?


回答1:


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)
}


来源:https://stackoverflow.com/questions/38766411/how-to-parameterize-a-selector-with-a-function-in-ef-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!