2009-07-07 148 views
5

有很多关于SO已经有大约左Linq中的联接问题,我已经看了所有的人使用join关键字来达到预期的结束。左加入Linq?

这是没有道理给我。假设我有CustomerInvoice的表格,通过Invoice上的外键CustomerID连接。现在我想运行包含客户信息和任何发票的报告。 SQL是:

select c.*, i.* 
    from Customer c 
    left join Invoice i on c.ID = i.CustomerID 

从我上见过这样的答案,人们大多提示:

var q = from c in Customers 
     join i in Invoices.DefaultIfEmpty() on c.ID equals i.CustomerID 
     select new { c, i }; 

我真不明白这是如何的唯一途径。 LinqToSQL类已经定义了CustomerInvoice之间的关系;为什么我不得不重复join条款?如果我想要一个内部联接它只会一直:

var q = from c in Customers 
     from i in c.Invoices 
     select new { c, i }; 

不指定加盟领域!

我想:

var q = from c in Customers 
     from i in c.Invoices.DefaultIfEmpty() 
     select new { c, i }; 

但只是给了我同样的结果,好像它是一个内部联接。

是不是有这样做的更好的办法?

回答

5

你在说什么? from i in c.Invoice.DefaultIfEmpty()就是一个左连接。

 List<string> strings = new List<string>() { "Foo", "" }; 

     var q = from s in strings 
       from c in s.DefaultIfEmpty() 
       select new { s, c }; 

     foreach (var x in q) 
     { 
      Console.WriteLine("ValueOfStringIs|{0}| ValueOfCharIs|{1}|", 
       x.s, 
       (int)x.c); 
     } 

这个测试将生成:

ValueOfStringIs|Foo| ValueOfCharIs|70| 
ValueOfStringIs|Foo| ValueOfCharIs|111| 
ValueOfStringIs|Foo| ValueOfCharIs|111| 
ValueOfStringIs|| ValueOfCharIs|0| 
2

您可能可能要使用“到”关键字。

Example

+0

谢谢,但是这并没有真正回答我的问题......是不是有更好的办法,采取的这种关系已经被定义的事实优势? – 2009-07-07 14:42:11

6

虽然关系已经被定义(两者在数据库中,并在标记的.dbml)运行时不能自动确定其是否应使用的关系。

如果有对象模型两个关系(人有父母和孩子,其他人都实例关系)。虽然案件可能是特殊案件,但这会使系统更复杂(所以更多的错误)。记住在SQL中,你会重复关系的规范。

记住索引和键是实现的细节,而不是关系模型的基础代数的一部分。

如果你想有一个LEFT OUTER JOIN,那么你需要使用 “into”:

from c in Customers 
join i in Invoices on i.CustomerId equals c.CustomerId into inv 
... 

和INV将有类型IEnumerable<Invoivce>,可能没有实例。

+0

+1好答案,但你仍然错过了我的观点。发票具体定义了“客户”关系,我想利用这种关系:“c。发票”,而不仅仅是“发票”。有没有办法做到这一点? – 2009-07-07 16:12:25

+0

@Shaul:然后这样做,只需在表达式中使用c.Invoices。如果你想要一个不同的标识符,那么使用let子句。 – Richard 2009-07-08 09:57:13