【问题标题】:Expression Tree for Aggregate Function in LINQ to EntitiesLINQ to Entities 中聚合函数的表达式树
【发布时间】:2015-02-03 04:49:14
【问题描述】:

我需要在 LINQ to Entities 查询之上动态替换一个聚合函数以在数据库中执行操作,同时不要硬编码我使用什么函数,例如在这样的查询中将Average() 替换为Max()Min()

IQueryable<Order> orders = ordersRepository.GetAll();
var q = from o in orders
        group o by o.OrderDate into g
        select new
        {
            OrderDate = g.Key,
            AggregatedAmount = g.AsQueryable()
                                .Average(x => x.Amount)
        };

我坚持将Queryable.Average() 转换为表达式树,该树可以放入查询中并成功转换为 SQL。

【问题讨论】:

  • 你能提供更多关于你到目前为止所尝试的细节吗?有一个小型库允许您将任意表达式插入到查询中。我现在不记得它的名字了。
  • @usr:这是我的问题。我不知道如何接近,从哪里开始。谷歌充满了 where 子句的谓词构建器,毫无疑问,这很容易。但似乎没有人尝试编写选择器。

标签: c# linq entity-framework linq-to-entities aggregate-functions


【解决方案1】:

g.Average(x =&gt; x.Amount)Queryable.Average(g, x =&gt; x.Amount)。我们要替换 Queryable.Average 部分。像这样:

Expression<Func<IQueryable<Order>, Func<Order, double>>> aggregate = ...;

然后使用表达式:

AggregatedAmount = aggregate(g, x => x.Amount)

问题是你不能调用表达式。所以使用AsExpandable:

var q = from o in orders.AsExpandable()
...
AggregatedAmount = aggregate.Compile()(g, x => x.Amount)

这会将aggregate 内联到查询表达式中,这样 EF 甚至都不知道它的存在。

【讨论】:

  • 嗯,你确定我需要打电话给Complle()()吗?我收到一个错误:无法将 System.Linq.Expressions.InstanceMethodCallExpressionN 类型的对象转换为 System.Linq.Expressions.LambdaExpression 类型。
  • 这些没有多大帮助:stackoverflow.com/questions/2564975/… stackoverflow.com/questions/23629442/… 或者我只是忽略了。
  • 嗯。它适用于IQueryable,但不适用于IGroupping。我希望会弄清楚)
  • 好吧,如果有任何问题,只能是 AsExpandable 代码。您交给 EF 的表达式应该与手动编写的代码没有区别。也许您需要深入研究 AsExpandable。我不认为它做任何真正复杂的事情。它应该只是将表达式“粘贴”到树中。基本上将 a.Compile().Invoke(x) 转换为 a(x)。
猜你喜欢
  • 2016-04-17
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2019-05-16
  • 1970-01-01
  • 2011-05-24
  • 2017-09-24
  • 1970-01-01
相关资源
最近更新 更多