Иметь оговорку в EF Linq - PullRequest
       3

Иметь оговорку в EF Linq

0 голосов
/ 11 октября 2018

Я хочу получить список идентификаторов клиентов и количество заказов, сделанных этим клиентом.Условия фильтрации:

  1. Заказы на общую сумму 10 долл. США или менее не будут учитываться.
  2. Клиенты, которые не разместили не менее 3 заказов (каждый на общую сумму 10 долл. США или более) не будут перечислены.

Итак, я бы сделал следующее в SQL:

SELECT customerID, COUNT(*)
FROM Orders
WHERE orderTotal > 10
GROUP BY customerID
HAVING COUNT(*) > 2

А в EF, я думаю, это можно выразить как:

dbContext.Order
.Where(o => o.orderTotal > 10)
.GroupBy(o => o.customerID)
.Where(g => g.Count() > 2)
.ToList();

Но это приводит к следующему SQL, который использует производную таблицу и объединение, а не просто с помощью предложения HAVING.Я думаю, что это было бы далеко не оптимально с точки зрения производительности.Есть ли лучший способ сформулировать регистр в EF, чтобы переведенный запрос использовал предложение HAVING, как и должно быть?

SELECT 
    [Project1].[C1] AS [C1], 
    [Project1].[customerID] AS [customerID], 
    [Project1].[C2] AS [C2], 
    [Project1].[ID] AS [ID], 

FROM ( SELECT 
    [GroupBy1].[K1] AS [customerID], 
    1 AS [C1], 
    [Extent2].[ID] AS [ID], 
    CASE WHEN ([Extent2].[storeID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
    FROM   (SELECT 
        [Extent1].[customerID] AS [K1], 
        COUNT(1) AS [A1]
        FROM [dbo].[Orders] AS [Extent1]
        WHERE [Extent1].[orderTotal] > cast(10 as decimal(18))
        GROUP BY [Extent1].[customerID] ) AS [GroupBy1]
    LEFT OUTER JOIN [dbo].[Orders] AS [Extent2] ON ([Extent2].[orderTotal] > cast(10 as decimal(18))) AND (([GroupBy1].[K1] = [Extent2].[customerID]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent2].[customerID] IS NULL)))
    WHERE [GroupBy1].[A1] > 2
)  AS [Project1]
ORDER BY [Project1].[customerID] ASC, [Project1].[C2] ASC

1 Ответ

0 голосов
/ 12 октября 2018

Что ж, запрос LINQ to Entities не эквивалентен запросу SQL, поскольку он возвращает список группировок (пара ключевых и совпадающих элементов), который вообще не имеет эквивалента SQL.

Если вы вернете только customerId и Count, как в запросе SQL:

db.Orders
.Where(o => o.orderTotal > 10)
.GroupBy(o => o.customerID)
.Select(g => new { customerId = g.Key, orderCount = g.Count() })
.Where(g => g.Count > 2)
.ToList();

, тогда SQL, сгенерированный EF, будет почти таким же (или функционально эквивалентным)ожидается:

SELECT
    [GroupBy1].[K1] AS [customerID],
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT
        [Extent1].[customerID] AS [K1],
        COUNT(1) AS [A1]
        FROM [dbo].[Orders] AS [Extent1]
        WHERE [Extent1].[orderTotal] > cast(10 as decimal(18))
        GROUP BY [Extent1].[customerID]
    )  AS [GroupBy1]
    WHERE [GroupBy1].[A1] > 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...