使用 Linq to Sql 的左外连接结果问题

Posted

技术标签:

【中文标题】使用 Linq to Sql 的左外连接结果问题【英文标题】:Left Outer Join Result Issue Using Linq to Sql 【发布时间】:2011-02-27 13:59:37 【问题描述】:

我们有以下查询来给我们一个左外连接:

(from t0 in context.accounts
           join t1 in context.addresses
                 on new  New_AccountCode = t0.new_accountcode, New_SourceSystem = t0.new_sourcesystem, New_Mailing = t0.new_MailingAddressString 
             equals new  New_AccountCode = t1.new_AccountCode, New_SourceSystem = t1.new_SourceSystem, New_Mailing = t1.new_MailingAddressString  into t1_join           
           from t1 in t1_join.DefaultIfEmpty()          
           where
             t0.statecode != 1 &&
             t0.statuscode != 2 &&
             t1.new_AccountCode == null &&
             t1.new_SourceSystem == null &&
             t1.new_MailingAddressString == null                   
           select t0)
           .OrderBy(o => o.new_accountcode)
           .ThenBy(o2=>o2.new_sourcesystem)
           .Skip(recordsProcessed)
           .Take(recordBatchSize).ToList();

问题在于,如果左表(帐户)包含具有相同帐户代码值的多行,则结果集包含重复的第一行 - 因此具有帐户代码、源系统和邮件地址字符串的唯一组合的第二行被“覆盖” .

Given:
accounts
accountcode     sourcesystem     mailingaddressstring
10025           ss1              12345
10025           ss2              67891

addresses
accountcode     sourcesystem     mailingaddressstring
10025           ss1              12345
10025           ss2              67891

we get:
accountcode     sourcesystem     mailingaddressstring
10025           ss1              12345
10025           ss1              12345

我们对 select 语句做错了吗?

谢谢

【问题讨论】:

给定的组合是一个地址还是多个?因为连接会产生可能的匹配。如果您有一个具有三个地址的帐户,则查询的结果将是该帐户的三行。您的查询语法没有错误,但您可能需要以不同的方式解决问题。 如果我理解你的话,每一行都有一个唯一的 accountcode、sourcesystem 和 mailingaddressstring 组合。只有 LINQ 结果集出现重复似乎仅基于 accountcode 列。 另外,我们可以删除插入到 t1_join 后的所有代码,并简单地替换为“select t0”。所以其他子句都不会影响结果。有趣的是,在 LinqPad 中,如果我们尝试:选择 new C1 = t0.new_accountcode, C2=t0.new_sourcesystem, C3=new_mailingaddressstring 那么问题就消失了。这并不能解决我们的问题,因为在运行时我们不能使用匿名类型,也不能选择新的 Account 对象(选择新的 Account ...)! 【参考方案1】:

啊,那好多了。左连接对我来说看起来很漂亮......但我觉得一切都不合适。

这些列中的任何(或全部)是主键吗? 数据上下文的生命周期是什么?以前是用来查询的吗?以前是用来保存记录的吗?

假设我有一个 Order 记录,其中 OrderId 设置为 dbml 中的主键(但不在数据库中,允许创建重复记录)。如果我要查询订单,并且 OrderID = 5 在那里两次......当数据上下文看到第一个具有 OrderID 的实例时,它开始跟踪它。当它看到第二个实例时,它不会对行进行水合,而是返回它已经返回的 ID=5 的实例。

如果我的查询结果是匿名类型,我不会看到这种行为,因为匿名类型在 dbml 中没有主键,并且不会被数据上下文跟踪。

【讨论】:

嘘。抱歉 - 我们复制了查询的简化版本。我已经编辑了查询,所以它是完整版本。道歉!!! 太棒了!就是这样,感谢 DB,只有 accountcode 是主键!所以我猜 Linq 可以管理连接,但在触发选择时不能区分对象?干杯! 很高兴听到。拍摄实例水合器的一种方法是捕获查询(sql profiler)并手动检查结果。如果数据库结果与返回的实例不匹配,宾果 - 它必须是实例水合器。

以上是关于使用 Linq to Sql 的左外连接结果问题的主要内容,如果未能解决你的问题,请参考以下文章

Linq to Entity 具有多个左外连接

Linq to SQL 使用 Lambda 语法进行左外连接并在 2 列上连接(复合连接键)

LINQ查询中的左外连接[重复]

将两个查询的左外连接转换为 LINQ

在 Linq 中使用左外连接

LINQ:具有多个条件的左外连接