实体框架执行表达式

时间:2014-03-19 08:52:30

标签: linq entity-framework linq-to-entities expression deferred-execution

这是简化代码

from oi in orderItems
    group oiGrouped by ...
    into orderItemsGroupedBySomething
    select new
    {
        Key = orderItemsGroupedBySomething.Key,

        Revenue = /*Here is some code that I want to extract to separate method, for example*/ 
            orderItemsGroupedBySomething.Sum(x => x.UnitPrice * x.Quantity)                     
    }

实际上在我的情况下它更复杂。但我觉得没关系。我无法提取orderItemsGroupedBySomething.Sum(x => x.UnitPrice * x.Quantity)的简单方法计算,因为它不是EntityFramework的已知方法。我试过把它放到表达式但我得到错误"The LINQ expression node type 'Invoke' is not supported in LINQ to Entities."我在查询中使用它之前编译了表达式,我认为因此我得到了错误。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

我不知道你需要它是多么通用,但这样的事情应该有效:

void Main()
{
    OrderItems.GroupBy(oi => oi.SomeProp).Select(GetExpression());
}

public Expression<Func<IGrouping<KeyType, OrderItem>, dynamic>> GetExpression()
{
    return (ig) => new { Key = ig.Key, Revenue = ig.Sum(x => x.UnitPrice * x.Quantity) };
}

编辑:在分组的情况下,我可能会返回一个元组而不是匿名类型。

答案 1 :(得分:1)

我添加了返回表达式的方法

public Expression<Func<OrderItem, decimal>> GetExpression()
{
    return x => x.UnitPrice*x.Quantity;
}

然后我试了

from oi in orderItems
    group oiGrouped by ...
    into orderItemsGroupedBySomething
    select new
    {
        Key = orderItemsGroupedBySomething.Key,
        Revenue =  orderItemsGroupedBySomething.Sum(GetExpression())                     
    }

但它不能用@LorentzVedeler回答。因为orderItemsGroupedBySomething属于IGrouping类型,它没有带有Expression类型的参数的Sum方法。所以我试过

orderItemsGroupedBySomething.AsQueryable.Sum(GetExpression())

但它会导致Internal .NET Framework Data Provider error 1025。问题是我在linq中调用了GetExpression()方法。为了解决这个问题,我将表达式置于局部变量中。结果

var expression = GetExpression();

from oi in orderItems
        group oiGrouped by ...
        into orderItemsGroupedBySomething
        select new
        {
            Key = orderItemsGroupedBySomething.Key,
            Revenue =  orderItemsGroupedBySomething.AsQueryable.Sum(expression)                     
        }