Учитывая объект, называемый фрукты:Смешивание Func и Expression Предикаты в Linq Для Entity запросов
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 < строки, фрукты>» не содержит определение для «Все» и лучшей перегрузки системы метода расширения». Linq.Enumerable.All < TSource> (System.Collections.Generic.IEnumerable < TSource>, System.Func < TSource, BOOL>)»имеет некоторые недопустимые аргументы
Но когда внешний предикат заключен в выражение:
Expression<Func<IGrouping<string, Fruit>, bool>> outerPredicate =
group => group.All(fruit => fruit.Edible);
var familiesWithAllEdibleFruits = context
.Fruits
.GroupBy(fruit => fruit.Family)
.Where(outerPredicate);
все работает правильно.
Я хотел бы понять поведение, которое я вижу здесь лучше. Похоже, что вызов «Все» внутри внешнего предиката не позволит использовать параметры выражения. Можно ли легко составлять запросы взаимозаменяемо с помощью Funcs и выражений (как во втором примере), или это неотъемлемое ограничение?
Этот вопрос может быть связан с http://stackoverflow.com/questions/19930389/expression-tree-with-linq-expressions – rtev