我的代码非常像这样:
Context.History.GroupBy(d => new { d.Category, d.Month })
.Select(group => new
{
Category = group.Key.Category,
Month = group.Key.Month,
// Geometric mean:
Value = Math.Exp(group.Average(a => Math.Log(a.Value)))
})
.GroupBy(d => d.Month)
.Select(monthly => new Dto {
Month = monthly.Month,
Average = monthly.Average(a => a.Value)
});
还有其他几个地方我计算了几何平均值,所以我想把它放在一个扩展方法中,所以注释后面的行看起来像Value = group.GeometricMean(a => a.Value)
.
如果我在 上编写常规扩展方法
IEnumerable<T>
,实体框架会抱怨它无法将其转换为查询。如果我编写一个在 上操作的方法
IQueryable<T>
,我会被告知group
实际上不是一个IQueryable<T>
,而是一个IGrouping<TKey, T>
.尝试将其称为“
Value = group.AsQueryable().GeometricMean(a => a.Value)
IGroupingArgumentException
类型的表达式不能用于 IQueryable 类型的参数(参数 arg0)”。
在我看来,我必须以某种方式将其IGrouping
转化IQueryable
为我的扩展方法才能工作,但我不知道如何。有一些关于 SO 的问题在该主题附近徘徊,但我发现没有一个问题适用于此。到目前为止,EF 可能根本不支持此功能。
更多信息:用某些功能替换整个Select
身体是行不通的,因为关键是要使几何平均计算可重用 - 其余部分根本不可重用。它需要在 SQL 中完成,因为它被证明太慢而无法获取数据并在 C# 中进行计算。
查看一些IQueryable
扩展方法的来源,似乎扩展方法的主体会构建一些表达式树并将其传递给source.Provider.Execute
. 我想我可能已经管理了那部分,但由于上述问题,我无法正确测试它。