当我在查询表达式语法中编写Group By
时,编译器会自动选择Enumerable.GroupBy
作为我的预期目标方法,然后返回IEnumerable
而不是IQueryable
。这意味着后续的g.Sum
来电(我的Select
内)需要Func(Of TSource, int)
而不是Expression(Of Func(Of TSource, int))
。有没有办法强制Group By
使用Queryable.GroupBy
而是给我一个IQueryable
?
受控示例代码
Dim myQuery = From x In DataSource.Items
Group By x.Key Into g = Group
Select New With {
.Key = Key,
.RedItems = g.Sum(ItemsOfColor(Colors.Red)) '<== invalid because g.Sum expects a lambda
}
Private Function PurpleItems(color As Integer) As Expression(Of Func(Of Item, Integer))
Return Function(item) If(item.Color = color, 1, 0)
End Function
我为什么要这样做?
编译器根据目标变量类型自动在lambda和表达式之间进行转换(即Dim f As Func(Of String, Integer) = Function(x) x.Length()
和Dim e As Expression(Of Func(Of String, Integer)) = Function(x) x.Length()
都有效),因此IEnumerable
之间的代码没有明显差异和IQueryable
。
问题是,LINQ to Entities(我假设其他db支持的LINQ实现)依赖于表达式树来转换为SQL。这意味着IEnumerable
lambda版对IDbSet
的{{1}}无法正常工作,就像我在this旧问题中找到的那样。
答案 0 :(得分:2)
问题在于Queryable.GroupBy()
会返回IQueryable<IGrouping<TKey, TSource>>
,其中IGrouping<TKey, TSource>
实施IEnumerable<TSource>
,而不是IQueryable<TSource>
。
我相信你的代码无论如何都行不通,因为ItemsOfColor()
实际上不会被调用。相反,EF会得到一个调用ItemsOfColor()
的表达式。由于它不知道该方法,因此会引发异常。