如何在EF查询中使用函数参数化选择器? [英] How to parameterize a selector with a function in EF query?

查看:184
本文介绍了如何在EF查询中使用函数参数化选择器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个传递给IQueryable<>.Select()方法的投影函数:

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

这样我就可以这样称呼

prices.Select(GetPriceSelector(e => Math.Round(e.Price, 4)))

不幸的是,英孚抱怨它:

Unfortunately, EF complains about it:

LINQ不支持LINQ表达式节点类型'Invoke' 实体

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities

如何重写代码以使EF满意?

How to rewrite the code to make EF happy?

推荐答案

首先,GetPriceSelector方法需要采用表达式,而不是函数.区别在于,表达式是作为数据的代码,因此可以将其转换为SQL,而将函数编译为代码,则不能将其转换为SQL.

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.

接下来,您需要一种合并两个表达式的方法.手动执行此操作很困难.幸运的是,有一个名为 LINQKit 的库可以做到这一点.这是使用LINQKit解决问题的方法:

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

这篇关于如何在EF查询中使用函数参数化选择器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆