2009-07-07 20 views
5

Linq'de sol birleşimler hakkında SO hakkında çok fazla soru var ve hepsine baktığımda istediğim uca ulaşmak için join anahtar sözcüğünü kullanın.Linq'de sola katıl?

Bu bana mantıklı gelmiyor. CustomerID ile ve Invoice tablolarına sahip olduğumu varsayalım. Şimdi müşteri bilgilerini içeren bir raporu ve ayrıca faturaları çalıştırmak istiyorum. SQL olacaktır: SO üzerinde cevapların gördüklerime, insanlar çoğunlukla öneriyorlar

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

Gönderen:

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

Gerçekten bu tek yol nasıl olabilir anlamıyorum. Customer ve Invoice arasındaki ilişki, LinqToSQL sınıfları tarafından zaten tanımlanmıştır; Neden join maddesi için tekrarlamak zorundayım? Ben bir iç isteseydim basitçe olurdu katılmak: katılmış alanları belirtmeden

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 }; 

ancak bir iç birleşim sanki sadece bana aynı sonucu verdi:

denedim.

Bunu yapmanın daha iyi bir yolu yok mu?

cevap

5

Ne hakkında konuşuyorsunuz? Bu from i in c.Invoice.DefaultIfEmpty() tam olarak bir sol birleştirmedir.

ValueOfStringIs|Foo| ValueOfCharIs|70| 
ValueOfStringIs|Foo| ValueOfCharIs|111| 
ValueOfStringIs|Foo| ValueOfCharIs|111| 
ValueOfStringIs|| ValueOfCharIs|0| 
+1

Beni havaya uçur - haklısın! Şimdi, neden bunun çalışmadığını düşündüm ...? Tamam, alçakgönüllü bir şekilde geri döndüm ... bu soru kendi yanlış anlamadığımdan kaynaklandı. TEŞEKKÜRLER! :) –

2

Muhtemelen 'into' anahtar sözcüğünü kullanmak isteyebilirsiniz.

Example

+0

Teşekkür, ama bu gerçekten benim soruya cevap vermez ... değil ilişki zaten tanımlı olmasına yararlanarak, daha iyi bir yolu vardır:

 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); } 

Bu test üretir? –

6

ilişki zaten bu ilişkiyi kullanmalıdır otomatik belirleyemez (veritabanında ve .dbml işaretlemesinde ikisi) çalışma zamanı tanımlanır iken.

Nesne modelinde iki ilişki varsa (Kişinin Ebeveynleri ve Çocukları, diğer Kişilerle olan ilişkileri). Vakalar özel kasalar olsa da, bu durum sistemi daha karmaşık hale getirecektir (daha fazla hata). SQL'de hatırla, ilişkinin özelliklerini tekrarlarsınız.

Dizinler ve anahtarlar, ilişki modelinin altında yatan ilişkisel cebirin bir parçası değil, bir uygulama ayrıntısıdır.

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

ve inv muhtemelen hiçbir örneği olacak biçimde tip IEnumerable<Invoivce> sahip olacaktır: Bir SOL DIŞ siz "into" kullanmak gerekir sonra JOIN istiyorsanız

.

+0

+1 İyi cevap, ama hala benim noktayı kaçırıyorsun.Fatura özel olarak tanımlanmış bir "Müşteriler" ilişkisine sahiptir ve bu ilişkiden yararlanmak istiyorum: "c.Invoices", sadece "Faturalar" değil. Bunu yapmanın bir yolu var mı? –

+0

@Shaul: Öyleyse yapın, sadece c.Invoices ifadesinde kullanın. Farklı bir tanımlayıcı istiyorsanız, bir izin cümlesi kullanın. – Richard