2011-12-21 108 views
1

到目前为止,我已经看到很多关于多个内部联接的SO问题,但是他们都没有解决我的问题。我一直在尝试在两个表上进行内部连接,并使用上一个表中的一个在第三个表上进行子查询。Linq to Sql - 使用具有多个参数的多个内部联接

这里的SQL代码:

SELECT 
//It's a lot of select fields here. Nothing really useful to solve the problem 
FROM 
    SCHEDULES 
INNER JOIN 
    STATUS 
ON 
    SCHEDULES.COMPANY    = STATUS.COMPANY   AND 
    SCHEDULES.BANK     = STATUS.BANK    AND 
    SCHEDULES.PRODUCT    = STATUS.PRODUCT   AND 
    SCHEDULES.IDSTRING    = STATUS.IDSTRING   AND 
    SCHEDULES.RECEIVER  = 'ADMILSONDAMASCENO'  AND 
    SCHEDULES.SCHEDULING < GETDATE()     AND 
    SCHEDULES.IDSTRING IN (
     SELECT DISTINCT IDSTRING FROM DEBTS_BBRASIL WHERE 
     DEBITOS_BBRASIL.COMPANY  = SCHEDULES.COMPANY  AND 
     DEBITOS_BBRASIL.BANK   = SCHEDULES.BANK   AND 
     DEBITOS_BBRASIL.PRODUCT  = SCHEDULES.PRODUCT  AND 
     DEBITOS_BBRASIL.IDSTRING  = SCHEDULES.IDSTRING  AND 
     DEBITOS_BBRASIL.STATUS   <> 2 
) 
ORDER BY SCHEDULES.SCHEDULING DESC 

,这里是搞什么名堂试图与LINQ做SQL:

from sched in SCHEDULES 
    join status in STATUS 
     on new { sched.IDSTRING, sched.COMPANY, sched.BANK, sched.PRODUCT } 
     equals new { status.IDSTRING, status.COMPANY, status.BANK, status.PRODUCT } 
    into schedStats 
    from ss in schedStats 
    join debt in DEBITOS_BBRASILs 
     on new { ss.IDSTRING, ss.COMPANY, ss.BANK, ss.PRODUCT } 
     equals new { debt.IDSTRING, debt.COMPANY, debT.BANK, debt.PRODUCT } 
    where sched.RECEIVER.Equals("ADMILSONDAMASCENO") && 
         sched.SCHEDULING <= DateTime.Now && debt.STATUS != 2 
    select new ScheduledStatus 
    { 
     //Lots of properties here 
    }; 

上面的代码,但是,产生Cross-Join那么Inner-Join,这我积极的是重复一些结果。在SqlServer上测试第一个代码产生了189个结果,而我的linq to sql代码产生了546个结果。我不知道如何重现相同的SQL代码LINQ到SQL代码。

我已经在linqPad上测试了它,只是为了确定。

+0

您是否尝试过查看生成的sql查询线索? DbContext.Log = Console.Out(其中DbContext是您的dbContext)将在调试时将生成的SQL放入您的输出窗口。 – 2011-12-21 17:18:34

+1

由于您已经有了TSQL,为什么不使用表值函数?然后使用LINQ to SQL调用函数。 http://msdn.microsoft.com/en-us/library/ms191165(v=SQL.100).aspx – Dave 2011-12-21 17:34:40

+0

不知道表值函数,感谢您的显示。但是,我不能使用它,因为我们有严格的策略,不要在数据库上放置任何逻辑。 – AdrianoRR 2011-12-22 12:37:46

回答

1

找到我的答案后,大量的'谷歌搜索'。我需要一个子查询来在另一个表上执行搜索,而不是另一个连接。使用linq to sql方法Any做了诀窍。这里最能帮助我的the post

而这里的的LINQ to SQL代码翻译我的TSQL代码:

from sched in SCHEDULES 
     join status in STATUS 
      on new { sched.IDSTRING, sched.COMPANY, sched.BANK, sched.PRODUCT } 
      equals new { status.IDSTRING, status.COMPANY, status.BANK, status.PRODUCT } 
     where sched.RECEIVER.Equals("ADMILSONDAMASCENO") && 
       sched.SCHEDULING <= DateTime.Now && DEBITOS_BBRASILs.Any(dbb=> 
        dbb.IDSTRING.Equals(sched.IDSTRING) 
        && dbb.COMPANY.Equals(sched.COMPANY) 
        && dbb.BANK.Equals(sched.BANK) 
        && dbb.PRODUCT.Equals(sched.PRODUCT) 
        && dbb.STATUS != 2) 
     select new ScheduledStatus 
     { 
     //Lots of properties here 
     }; 
1

当使用LINQ to SQL中明确连接通常不应该被使用。如果你建立了正确的关系,你应该有可以使用的导航属性。有了这些,查询将是这样的:

from sched in SCHEDULES 
where sched.status.debt != 2; 

如果数据库中的外键,导航属性将自动通过SqlMetal.exe或由人或者设计人当你放下设计者的两个表生成表面。这些表格之间的关系将以一条线显示(请参阅下面的示例)。

Sample navigation properties

+0

我同意你的意见。我在一些博客上看过它。这就是所谓的关联,对吗?不幸的是,我工作的数据库在这些表上没有该关联(通过fk)。更糟的是,我无法改变它,因为它是一个遗留系统,取决于当前这些表的工作方式。无论如何,谢谢你的回答。 – AdrianoRR 2011-12-23 03:40:18

+0

您也可以在OR设计器中手动添加关联,而不会影响数据库。 – 2011-12-23 08:34:10