EFCore 对于简单的 LEFT OUTER 连接返回太多列

2023-11-23

我目前正在将 EFCore 1.1(预览版)与 SQL Server 结合使用。

我正在做我认为是一个简单的 OUTER JOIN 之间的事情Order and OrderItem table.

      var orders = from order in ctx.Order
                   join orderItem in ctx.OrderItem

                   on order.OrderId equals orderItem.OrderId into tmp

                   from oi in tmp.DefaultIfEmpty()

                   select new
                   {
                       order.OrderDt,
                       Sku = (oi == null) ? null : oi.Sku,
                       Qty = (oi == null) ? (int?) null : oi.Qty
                   };

返回的实际数据是正确的(我知道早期版本存在 OUTER JOINS 根本不起作用的问题)。然而 SQL 很糟糕并且包含了中的每一列Order and OrderItem考虑到其中一个是大型 XML Blob,这是有问题的。

SELECT [订单].[OrderId], [订单].[OrderStatusTypeId], [订单].[OrderSummary]、[订单].[OrderTotal]、[订单].[OrderTypeId]、 [订单].[ParentFSPID], [订单].[ParentOrderId], [订单]。[PayPalECToken],[订单]。[PaymentFailureTypeId] ....

...[orderItem].[OrderId]、[orderItem].[OrderItemType]、[orderItem].[Qty]、 [orderItem].[SKU] FROM [订单] AS [订单] LEFT JOIN [OrderItem] AS [orderItem] ON [order].[OrderId] = [orderItem].[OrderId] ORDER BY [订单].[订单ID]

(还有更多列未在此显示。)

另一方面 - 如果我将其设置为 INNER JOIN,则 SQL 与预期一致,仅包含我的 select 子句中的列:

SELECT [订单].[OrderDt]、[orderItem].[SKU]、[orderItem].[Qty] FROM [订单] AS [订单] INNER JOIN [OrderItem] AS [orderItem] ON [订单].[订单 ID] = [订单项].[订单 ID]

我尝试恢复到 EFCore 1.01,但遇到了一些可怕的 nuget 包错误并放弃了。

不清楚这是实际的回归问题还是 EFCore 中的不完整功能。但在其他地方找不到任何有关此的进一步信息。


编辑:EFCore 2.1 解决了许多分组问题以及 N+1 类型问题,其中为每个子实体进行单独的查询。事实上,对表演印象非常深刻。

2018 年 3 月 14 日 - 不建议使用 EFCore 2.1 预览版 1,因为 GROUP BY SQL 在使用 OrderBy() 时存在一些问题,但已在夜间构建和预览版 2 中修复。


以下内容适用于 EF Core 1.1.0(版本)。

虽然不应该做这样的事情,但尝试了几种替代语法查询(使用导航属性而不是手动连接,连接包含匿名类型投影的子查询,使用let/ 中间的Select, using Concat / Union模拟左连接、替代左连接语法等)结果 - 要么与帖子中的相同,和/或执行多个查询,和/或无效的 SQL 查询,和/或奇怪的运行时异常,例如IndexOutOfRange, InvalidArgument etc.

根据测试我可以说的是,问题很可能与错误(回归、不完整的实现 - 这真的很重要)有关吗?GroupJoin翻译。例如,#7003:为在最终投影中不存在的子查询上进行组联接的查询生成了错误的 SQL or #6647 - Left Join (GroupJoin) 总是具体化元素,导致不必要的数据拉取 etc.

直到它得到修复(什么时候?),作为一种(远非完美的)解决方法,我可以建议使用替代的左外连接语法(from a in A from b in B.Where(b = b.Key == a.Key).DefaultIfEmpty()):

var orders = from o in ctx.Order
             from oi in ctx.OrderItem.Where(oi => oi.OrderId == o.OrderId).DefaultIfEmpty()
             select new
             {
                 OrderDt = o.OrderDt,
                 Sku = oi.Sku,
                 Qty = (int?)oi.Qty
             };

生成以下 SQL:

SELECT [o].[OrderDt], [t1].[Sku], [t1].[Qty]
FROM [Order] AS [o]
CROSS APPLY (
    SELECT [t0].*
    FROM (
        SELECT NULL AS [empty]
    ) AS [empty0]
    LEFT JOIN (
        SELECT [oi0].*
        FROM [OrderItem] AS [oi0]
        WHERE [oi0].[OrderId] = [o].[OrderId]
    ) AS [t0] ON 1 = 1
) AS [t1]

正如你所看到的,投影是好的,但是不是LEFT JOIN它使用奇怪的CROSS APPLY这可能会引入另一个性能问题。

另请注意,在访问如上所示的右连接表时,必须对值类型使用强制转换,而对字符串不使用任何强制转换。如果你使用null按照原始查询进行检查,您将得到ArgumentNullException在运行时(又一个错误)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EFCore 对于简单的 LEFT OUTER 连接返回太多列 的相关文章

随机推荐

  • Flink 键控流密钥为空

    我正在尝试在 Flink 中的 KeyedStream 上执行映射操作 stream map new JsonToMessageObjectMapper keyBy keyfield map new MessageProcessorStat
  • 当应用程序在后台运行时 Android 传感器正在监听

    即使应用程序不在前台 是否可以连续跟踪 Android 上的运动传感器事件 如果是的话 电池的消耗是什么 一位客户询问是否可以编写一个应用程序 在人 跌倒 时启动一个动作 这基本上意味着不断监听运动传感器的快速移动 首先 您绝对可以在后台监
  • 无法在清单资源中找到该报告

    我将所有水晶报表保存在一个文件夹中 VOUCHERS gt SALE gt BILLFORMATS 例如 第一个报告的位置是 VOUCHERS gt SALE gt BILLFORMATS gt BillFormat1 rpt Vegi M
  • 如何绘制按日期聚合的 pandas 数据框

    我有这个数据框 df pd DataFrame 2017 01 14 1 2017 01 14 30 2017 01 16 216 2017 02 17 23 2017 02 17 2 2017 03 19 745 2017 03 19 3
  • 下面的掩码输入问题如何解决?

    我有一个脚本来屏蔽文本框 在这里它 我还有一个脚本可以在单击按钮时动态添加文本框
  • 将国家/地区名称转换为国家/地区代码缩写 php [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 有没有办法将国家名称转换为国家代码缩写 或者一些php函数 这样当 澳大利亚 时
  • 当我尝试在驱动器中搜索时,程序抛出 NullPointerException?

    我编写了一个程序来查找文件或目录 当我尝试使用 in 搜索文件时 它工作正常目录 example java FileSearch abc txt f xyz但是当我尝试从中搜索文件时本地驱动器比程序抛出异常 java FileSearch
  • C# 迭代枚举? (索引 System.Array)

    我有以下代码 Obtain the string names of all the elements within myEnum String names Enum GetNames typeof myEnum Obtain the val
  • Swift - 是什么决定了字典集合的顺序?

    当我说顺序时 我的意思是编译器选择显示结果的顺序 我知道字典没有像数组那样的索引 我有以下字典 let groups Dictionary
  • IDisposable GC.SuppressFinalize(this) 位置

    我的代码使用默认的 IDisposable 实现模板 模式 snippet public void Dispose Dispose true GC SuppressFinalize this protected virtual void D
  • 在 OS X 上安装 GCC 4.7.1

    我正在尝试安装GCC4 7 1 在我的 Mac 上 因为我想更新LLVM GCC4 2 XCode 中给出 我已经下载了GCC4 7 1 我已经放置了gcc 4 7 1文件夹中 Downloads 然后我按照此处给出的说明进行操作 http
  • 如何尽快实现strlen

    假设您使用的是 x86 32 位系统 您的任务是尽快实现 strlen 有两个问题你需要注意 1 地址对齐 2 以机器字长 4 个字节 读取内存 找到给定字符串中的第一个对齐地址并不难 然后我们可以用这4个字节读取一次内存 并计算总长度 但
  • 这是什么? (函数(){})()[重复]

    这个问题在这里已经有答案了 可能的重复 这个 JavaScript 片段是什么意思 自动执行匿名 JavaScript 函数的括号位置 function something here lt This part right here 这到底是
  • 为什么使用静态块而不是直接初始化实例变量?

    为什么我要使用静态块 static B 10 over Integer B 10 一种相对于另一种的优点 缺点是什么 The static块允许您为属性编写更复杂的初始化逻辑 而单行初始化将您限制为单个表达式 请注意 实例属性和静态属性都存
  • 中断线程自身

    我不明白为什么线程不抛出InterruptedException当自己被打断时 我正在尝试使用以下代码片段 公共类中断测试 public static void main String args MyThread t new MyThrea
  • 如何在 django 视图中使用 python 多处理模块

    我有一个简单的函数来遍历 URL 列表 使用GET检索一些信息并更新数据库 PostgresSQL 因此 该功能运行完美 然而 一次一个地浏览每个 URL 会花费太多时间 使用 python 我可以执行以下操作来并行这些任务 from mu
  • 使用Django Rest框架序列化自定义数据类型并返回响应

    大多数关于 Django Rest Framework 的教程都解释了如何使用 Django 模型并执行 CRUD 操作 这是一个GET如果我使用 JSON 序列化程序 对用户模型的请求将以 JSON 格式返回用户对象的属性 我正在设计 D
  • 使用 HTML 属性作为 CSS 属性值 [重复]

    这个问题在这里已经有答案了 规范说 attr 函数返回元素上的属性值 用作属性中的值 如果在伪元素上使用 它将返回伪元素的原始元素上的属性值 http www w3 org TR css3 values attr 然而 这似乎不起作用 当我
  • jQuery - 表单不会使用 jQuery 提交

    进一步解决我的问题 jQuery 提交验证 最后有模式对话框 看起来表单根本不会使用 jQuery 提交 这是我的非常简化的代码
  • EFCore 对于简单的 LEFT OUTER 连接返回太多列

    我目前正在将 EFCore 1 1 预览版 与 SQL Server 结合使用 我正在做我认为是一个简单的 OUTER JOIN 之间的事情Order and OrderItem table var orders from order in