LINQ和SQL中看似等效的查询返回不同的结果

本文关键字:查询 返回 结果 SQL LINQ | 更新日期: 2023-09-27 18:20:55

不确定为什么它被链接为重复。问题大不相同。答案不同。不知道该改变什么。如果有人看到我缺少的东西,请告诉我

我使用这两个查询得到了不同数量的结果。在分析了几个小时后,我需要认输,承认我无法发现显著性的差异。由于我的方法库被清空了,我请求帮助。

LINQ

List<Uno> result = context.Unos
  .Join(context.Duos, uno => uno.CommonId, duo => duo.CommonId,
    (uno, duo) => new { Uno = uno, Duo = duo })
  .Where(item => item.Uno.Amount > 0
    && item.Duo.Type == 2)
  .Select(item => item.Uno)
  .ToList();

SQL

select * from Uno as u
join Duo as d on d.CommonId = u.CommonId
where u.Amount > 0
  and d.Type = 2

第一个问题是,以上两种说法是否确实相等,或者我是否遗漏了什么。第二个问题是我遗漏了什么(如果有的话),或者如何解决(如果没有的话)。

  1. 对同一数据库进行调用
  2. 结果的数量相差甚远(142和1437)
  3. 为内部联接提取相同的结果集
  4. UnoDuo都是视图,而不是表

我还能验证什么?

编辑

经过社区的大力支持,我们确定LINQ查询可以通过以下命令进行SQL化。

var wtd = context.Unos
  .Join(context.Duos, uno => uno.CommonId, duo => duo.CommonId,
    (uno, duo) => new { Uno = uno, Duo = duo })
  .Where(item => item.Uno.Amount > 0
    && item.Duo.Type == 2)
  .Select(item => item.Uno)
  .ToString();

疯狂的是,在SQL管理器中执行那个字符串会产生142个结果(就像上面例子中的查询,SQL版本),它与它的区别很小。然而,执行LINQ查询本身会产生1437个结果。我太困惑了,甚至都哭不出来。。。

"SELECT ''r''n[Extent1]。[CommonId]AS[CommonId],''r''n[Extent1]。[X] AS[X]''r''n FROM(SELECT[Uno].[CommonId]AS[CommonId],''n[Uno].X]AS[X]''n FROM[Finance].[Uno]AS[Uno])AS[Extent1]''r''n INNER JOIN].[V]AS[V]''n FROM[Finance].[Duo]AS[Duo])AS[Extent2]ON[Extent1]。[CommonId]=[Extent2]。[CommonId]''r''n WHERE([Extent1].[X]>强制转换(0为十进制(18))AND([Extend2].[Type]=@p_linq__0)"

LINQ和SQL中看似等效的查询返回不同的结果

这是在实体框架中映射视图时经常发生的事情。与常规数据库表不同,视图通常没有明确的唯一键值。当EF遇到主键值相同的行时,它只是复制属于它已经知道的键的行。在联接中,这可能导致EF生成更多的子记录,因为第一个已知行可能比实际数据库行具有更多的子行。

修复方法是确保视图具有唯一标识行的字段(或字段组合)。当然,在EF中,这应该被映射为(可能是复合的)主键。

我不知道EF为什么会表现出这种行为。我认为它应该有可能抛出一个异常,即它具体化了重复的实体。这个"特性"总是引起很多混乱。

这是一个很长的机会,但这个LINQ表达式会改变什么吗?

(from uno in context.Unos
 join duo in context.Duos on uno.CommonId equals duo.CommonId
 where uno.Amount > 0 && duo.Type == 2
 select new {Uno = uno, Duo = duo}
).ToList()

我更喜欢这个表单,因为它看起来像真正的SQL请求。不知怎么的,你的LINQ中的Join语句让我很困扰…

调试此位置时,请尝试查看在IntelliTrace窗口中执行LINQ后运行的查询。然后与您的SQL相比,我认为它们是不同的。如果您没有IntelliTrace,请尝试Express Profiler。只需设置SQL Server的名称,单击"跟踪"并监视它。希望它能有所帮助!