【问题标题】:Entity Framework composing SQL in unexpected order以意外顺序组成 SQL 的实体框架
【发布时间】:2015-05-13 15:49:15
【问题描述】:

我有一个查询,它必须从满足某些详细信息的有序查询中获取前 15 项。所以我做了类似的事情:

var ten = repository
            .Orders
            .OrderByDescending(p => p.ClerkCode)
            .Select(o=>o.OrderId)
            .Take(10)
            ;

var orders = repository
                .Orders
                .Where(o => ten.Contains(o.OrderId))
                .Include(o => o.Products);

所以子查询获取所有符合条件的项目,而主查询只是完成信息。这会生成以下查询:

SELECT
[Project2].[OrderId] AS [OrderId],
[Project2].[CustomerId] AS [CustomerId],
[Project2].[ClerkCode] AS [ClerkCode],
[Project2].[C1] AS [C1],
[Project2].[ProductOrderId] AS [ProductOrderId],
[Project2].[ProductId] AS [ProductId],
[Project2].[OrderId1] AS [OrderId1],
[Project2].[Quantity] AS [Quantity]
FROM ( SELECT
    [Extent1].[OrderId] AS [OrderId],
    [Extent1].[CustomerId] AS [CustomerId],
    [Extent1].[ClerkCode] AS [ClerkCode],
    [Extent2].[ProductOrderId] AS [ProductOrderId],
    [Extent2].[ProductId] AS [ProductId],
    [Extent2].[OrderId] AS [OrderId1],
    [Extent2].[Quantity] AS [Quantity],
    CASE WHEN ([Extent2].[ProductOrderId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM  [dbo].[Orders] AS [Extent1]
    LEFT OUTER JOIN [dbo].[ProductOrders] AS [Extent2] ON [Extent1].[OrderId] = [Extent2].[OrderId]
    WHERE  EXISTS (SELECT
        1 AS [C1]
        FROM ( SELECT TOP (10) [Extent3].[OrderId] AS [OrderId]
            FROM [dbo].[Orders] AS [Extent3]
            ORDER BY [Extent3].[ClerkCode] DESC
        )  AS [Limit1]
        WHERE [Limit1].[OrderId] = [Extent1].[OrderId]
    )
)  AS [Project2]
ORDER BY [Project2].[OrderId] ASC, [Project2].[C1] ASC

我可以看到正在对有序子查询执行select top

现在问题来了。我想拿 10 个不同的项目,所以我将查询更改为:

var ten = repository
            .Orders
            .OrderByDescending(p => p.ClerkCode)
            .Select(o=>o.OrderId)
            .Distinct()
            .Take(10)
            ;

var orders = repository
                .Orders
                .Where(o => ten.Contains(o.OrderId))
                .Include(o => o.Products);

现在生成的SQL是这样的:

SELECT
[Project2].[OrderId] AS [OrderId],
[Project2].[CustomerId] AS [CustomerId],
[Project2].[ClerkCode] AS [ClerkCode],
[Project2].[C1] AS [C1],
[Project2].[ProductOrderId] AS [ProductOrderId],
[Project2].[ProductId] AS [ProductId],
[Project2].[OrderId1] AS [OrderId1],
[Project2].[Quantity] AS [Quantity]
FROM ( SELECT
    [Extent1].[OrderId] AS [OrderId],
    [Extent1].[CustomerId] AS [CustomerId],
    [Extent1].[ClerkCode] AS [ClerkCode],
    [Extent2].[ProductOrderId] AS [ProductOrderId],
    [Extent2].[ProductId] AS [ProductId],
    [Extent2].[OrderId] AS [OrderId1],
    [Extent2].[Quantity] AS [Quantity],
    CASE WHEN ([Extent2].[ProductOrderId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM  [dbo].[Orders] AS [Extent1]
    LEFT OUTER JOIN [dbo].[ProductOrders] AS [Extent2] ON [Extent1].[OrderId] = [Extent2].[OrderId]
    WHERE  EXISTS (SELECT
        1 AS [C1]
        FROM ( SELECT TOP (10) [c].[OrderId] AS [OrderId]
            FROM [dbo].[Orders] AS [c]
        )  AS [Limit1]
        WHERE [Limit1].[OrderId] = [Extent1].[OrderId]
    )
)  AS [Project2]
ORDER BY [Project2].[OrderId] ASC, [Project2].[C1] ASC

现在执行select top的子查询不是由ClerkCode排序的。

我该如何解决这个问题?

【问题讨论】:

  • 生成的 SQL 不完整 - 您的子查询没有返回列,它应该是 ORDER BY 而不是 ORDERBY。将您的实际代码减少到合理的大小(例如减少返回的列数),以便我们可以看到 ACTUAL sql。
  • 实际的 SQL 很大,所以我警告这是伪代码。
  • 但是你的伪代码SQL无效,所以我们无法知道实际结果是什么,或者如何适当地更改代码。
  • 当然是无效的,只是表示orderby是如何从子查询中取出来的,仅此而已。粘贴1000行sql不需要它。
  • 我在 LinqPad 中尝试过这样的事情,它似乎生成了你想要的 SQL。

标签: sql sql-server entity-framework entity-framework-6


【解决方案1】:

预期的行为是它返回源中唯一项的无序序列。

-- https://msdn.microsoft.com/en-us/library/bb348456


它依赖于实现,但Distinct 似乎会清除任何先前设置的排序。

【讨论】:

  • 谢谢这个解释。我认为 GroupBy 也会发生同样的事情。干杯。
猜你喜欢
  • 2019-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多