【问题标题】:LINQ to Entities chaining commands with differing resultsLINQ to Entities 链接具有不同结果的命令
【发布时间】:2018-06-13 19:03:27
【问题描述】:

我的问题比较笼统,但我有一个例子可以帮助说明:

db.aTable.Where(x => x.Date < someDateInThePast).OrderByDescending(x => x.Date).First()

这给了我一个项目,它与此命令返回的项目不同:

db.aTable.Where(x => x.Date < someDateInThePast).ToList().OrderByDescending(x => x.Date).First()

(注意中间的“ToList()”)。

据我所见,第一个示例中实际发生的情况是 OrderBy 完全无视 .Where() 完成的过滤。它正在订购整个aTable。 第二个查询给出了实际正确的项目。

.Date 参数是一个 DateTime 类型(在 SQL 端它是一个“日期时间”)。

LINQ to Entities 会出现这种行为吗?

【问题讨论】:

  • 可能你有几个具有相同最大值 Date 的项目,并且在数据库和客户端上订购从它们中选择不同的一个结果。您可以添加额外的排序,例如:.OrderByDescending(x =&gt; x.Date).ThenBy(x =&gt; x.Id) 以确保相同的结果。
  • 我的实际 LINQ 在 .Where() 中包含一个附加部分,该部分按 ID 过滤,每个 ID 每个日期最多有 1 个条目。无论如何我已经检查过了,对于第一个查询,我得到了一个日期为 27/11/2017 的项目。而第二个给出了 2018 年 3 月 15 日正确的最新一个。它几乎看起来像是在对原始字符进行排序(例如 27 > 15),但我无法证明它
  • 这是一个奇怪的问题,它甚至不是一个真正的问题,因为它不可能重现你的结果来回答。您需要创建一个最小示例、一个包含最少列和类型定义的表描述以及一些重现您的问题的示例数据。您还需要告诉我们您使用的是什么数据库。因为它不可能知道你看到了什么或为什么
  • 添加 ToList() 应该不会对 O/P 产生任何影响,但是正如 TheGeneral 所说,您需要使用 i/p 扩展代码以便其他人交叉验证一次
  • 什么是你的第一种方法生成的 sql 查询,你能检查一下吗

标签: c# linq


【解决方案1】:

通过添加.ToList(),您实际上更改了处理数据的上下文。

您的第一个查询完全由您的数据库处理,您只需将 .First() 的值返回给您的实体实例。

在第二个中,您基本上通过给他命令.ToList() 来给他命令加载条件aTable 然后订购它,添加第二个条件并从已经实例化的那个中选择第一个Date 值表。

Microsoft 声明 link 更改 CLR 可能会导致意外结果,这就是您正在做的事情。

确切知道发生了什么的一种方法是直接在 SQL Server 上执行语句:

Select Top(1) Date
From aTable
Where Date < someDateInThePast
order by Date desc

然后为您的数据创建一个数据库集,直到上下文发生变化:

Select * 
From aTable
Where Date < someDateInThePast
order by Date desc

然后在你的c#环境中单独调用。然后检查结果是否仍然不同。

希望这会有所帮助!

【讨论】:

  • 是的,但这不应该对最终结果产生影响。
  • 是的。您强制查询根据客户端的 CLR 运行,数据库除外。
  • 来源:link
  • 没有。 datetime 数据类型 100% 兼容并且(据我所知)处理相同。我确实知道 CLR 更改可能会导致意外结果,但我不能 100% 确定到底是什么原因造成的。我个人认为Date 属性不是罪魁祸首。我认为上下文的变化在声明中搞砸了。
  • 上面提到的其中一个 cmets 查看正在生成的 SQL。我注意到 SQL 中没有包含“Order By”语句。不确定它是否应该在那里。
【解决方案2】:

我无法完全解释为什么它会这样工作,但我发现包含 First() 是导致问题的原因。当我查看由 LINQ 生成的原始 SQL 时,其中没有对“Order By”的引用。我只能假设订购发生在客户端。但是,在 SQL 中引用了“TOP (1)”。意思是,因为 SQL 服务器只返回 1 个结果,所以 order by 只发生在 1 个结果上并且没有做任何有用的事情。

如果我将First() 更改为ToList(),那么排序将按预期工作。这并不能解决我的问题,但它解释了行为。

【讨论】:

  • 第二个查询 db.aTable.Where(x =&gt; x.Date &lt; someDateInThePast).ToList() 永远不会转换为 TOP (1) 查询。您是否显示了导致问题的确切代码?
  • 你是对的:第二个查询没有TOP 1。只有第一个查询可以。这就是第二个查询有效的部分原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 2014-10-07
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
相关资源
最近更新 更多