给定一个名为Fruit的实体:
public class Fruit
{
public int Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
public bool Edible { get; set; }
}
以下Linq-To-Entities查询:
var familiesWithAllEdibleFruits = context
.Fruits
.GroupBy(fruit => fruit.Family)
.Where(group => group.All(fruit => fruit.Edible));
生成一个选择正确记录的SQL语句:
SELECT
[Project4].[C1] AS [C1],
[Project4].[Family] AS [Family],
[Project4].[C2] AS [C2],
[Project4].[Id] AS [Id],
[Project4].[Name] AS [Name],
[Project4].[Family1] AS [Family1],
[Project4].[Edible] AS [Edible]
FROM ( SELECT
[Project2].[Family] AS [Family],
[Project2].[C1] AS [C1],
[Project2].[Id] AS [Id],
[Project2].[Name] AS [Name],
[Project2].[Family1] AS [Family1],
[Project2].[Edible] AS [Edible],
CASE WHEN ([Project2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
FROM ( SELECT
[Distinct1].[Family] AS [Family],
1 AS [C1],
[Extent2].[Id] AS [Id],
[Extent2].[Name] AS [Name],
[Extent2].[Family] AS [Family1],
[Extent2].[Edible] AS [Edible]
FROM (SELECT DISTINCT
[Extent1].[Family] AS [Family]
FROM [dbo].[Fruits] AS [Extent1] ) AS [Distinct1]
LEFT OUTER JOIN [dbo].[Fruits] AS [Extent2] ON ([Distinct1].[Family] = [Extent2].[Family]) OR (([Distinct1].[Family] IS NULL) AND ([Extent2].[Family] IS NULL))
) AS [Project2]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Fruits] AS [Extent3]
WHERE (([Project2].[Family] = [Extent3].[Family]) OR (([Project2].[Family] IS NULL) AND ([Extent3].[Family] IS NULL))) AND ([Extent3].[Edible] <> cast(1 as bit))
)
) AS [Project4]
ORDER BY [Project4].[Family] ASC, [Project4].[C2] ASC
但是下面的内部谓词是表达式的代码:
Expression<Func<Fruit, bool>> innerPredicate = fruit => fruit.Edible;
var familiesWithAllEdibleFruits = context
.Fruits
.GroupBy(fruit => fruit.Family)
.Where(group => group.All(innerPredicate));
卡在编译器的抓取中:
“System.Linq.IGrouping&LT; string,Fruit&gt;'不包含'All'的定义和最佳扩展方法重载'System.Linq.Enumerable.All&lt; TSource&gt;(System.Collections.Generic.IEnumerable&lt; TSource&gt;,System.Func&lt; TSource,bool&gt;)'有一些无效的参数
然而,当外部谓词被封装在表达式中时:
Expression<Func<IGrouping<string, Fruit>, bool>> outerPredicate =
group => group.All(fruit => fruit.Edible);
var familiesWithAllEdibleFruits = context
.Fruits
.GroupBy(fruit => fruit.Family)
.Where(outerPredicate);
事情正常。
我想了解我在这里看到的行为更好。看起来外部谓词中对“全部”的调用将不允许表达式参数。是否可以轻松地与Funcs和Expressions交换组合查询(如第二个例子)或这是一个固有的限制?
答案 0 :(得分:1)
您能够管理的最好的就是在这里使用LINQKit:
Expression<Func<Fruit, bool>> innerPredicate = fruit => fruit.Edible;
var familiesWithAllEdibleFruits = context
.Fruits
.GroupBy(fruit => fruit.Family)
.Where(group => group.All(fruit => innerPredicate.Invoke(fruit)))
.Expand();
至于为什么,您的第一个代码段包含的表达式表示表示Func
的表达式,而您想要的表达式只表示Func
。你需要一种方式解开&#34;表达方式。简而言之,这根本不容易。组合表达式比组成常规委托需要花费更多的工作,因为你需要解开每个表达式的主体并将其内联到外部表达式中。