2010-11-18 23 views
0

Hiyerarşik verileri düzleştirmek için SQL'i böyle kullanıyorum. Sadece bir görünüm oluşturup EF diyagramına atıyorum. Ancak bu, "SQL Management Studio'yu LinqPad ile değiştir" zihniyetine uymuyor. Bunları Linq (ve C#) 'de nasıl kodlarım? (Tablo 1 - Varlıklar/Varlık Çerçevesi 4)Linq Akrobasi: Hiyerarşik veri modelleri nasıl düzleştirilir?

Tablo A, ürünleri ve B tablosunu birçok kategoride bulundurmaktadır. Ben görünümünde tek alan olarak bir kategori numarası seçmek istiyor:

select A.*, B1.category as color, B2.category as size, B3.category as shape 
from A left join B B1 on A.key = B1.key and B1.type = 1 -- Selects one B row 
     left join B B2 on A.key = B2.key and B2.type = 2 
     left join B B3 on A.key = B3.key and B3.type = 3 

iyisi, SQL-aramak ve Linq eşdeğer görebileceğiniz bir Linq desen yemek kitabı var mı? C# 'da 101 Linq examples'u daha önce görmüştüm.

cevap

2

Ne yazık ki, ne LINQ bir dış birleştirme var, ne de rasgele birleştirme koşulları ekleyebilirsiniz. İç birleştirme DefaultIfEmpty kullanılarak çalışılabilir, ancak birleştirme koşulunun Bn.type = n kısmının bir koşul durumuna taşınması gerekir.

şu bahsettiğim tip maddeler haricindeki, sağladığınız tam SQL üretir

:

exec sp_executesql N'SELECT [t0].[key], [t1].[category] AS [color], [t2].[category] AS [size], [t3].[category] AS [shape] 
FROM [Product] AS [t0] 
LEFT OUTER JOIN [Category] AS [t1] ON [t0].[key] = [t1].[key] 
LEFT OUTER JOIN [Category] AS [t2] ON [t0].[key] = [t2].[key] 
LEFT OUTER JOIN [Category] AS [t3] ON [t0].[key] = [t3].[key] 
WHERE ([t1].[type] = @p0) AND ([t2].[type] = @p1) AND ([t3].[type] = @p2)',N'@p0 int,@p1 int,@p2 int',@p0=1,@p1=2,@p2=3 

(Update

from A in products 
join B1 in categories on A.key equals B1.key into tmp_color 
join B2 in categories on A.key equals B2.key into tmp_size 
join B3 in categories on A.key equals B3.key into tmp_shape 
from B1 in tmp_color.DefaultIfEmpty() 
from B2 in tmp_size.DefaultIfEmpty() 
from B3 in tmp_shape.DefaultIfEmpty() 
where B1.type == 1 && B2.type == 2 && B3.type == 3 
select new { product = A, color = B1.category, size = B2.category, shape = B3.category }; 

sonuçları: bu sadece varsayarak, LINQ to SQL bulunuyor EF olur o benzer.)

Albin'in cevabı daha okunaklıdır, ancak muhtemelen daha az optimal SQL üretir. SQL'inizle tam bir eşleşme için, FirstOrDefault öğesini DefaultIfEmpty ile değiştirmelisiniz (verilerinize bağlı olarak fark yaratamayabilirsiniz). (Maalesef henüz yorum yapamazsınız ;-))

+0

Minor point - LINQ'da kendi başına bir dış birleşim yoktur, ancak Entity Framework'de LINQ kullanılarak, dış birleşimlere yol açan birçok sorgu biçimi vardır - örneğin Var insanlar = db.Person.In Idde on eklendiğinde (p => p.Adres) null olamaz - EF sizin için sol dış birleşim olarak yorumluyor. –

2

Bir alt seçim yaklaşımı için giderdim.

from a in ModelEntities.A 
select new 
{ 
    f1 = a.f1, 
    f2 = a.f2, 
    // ..., 
    fn = a.fn, 
    color = ModelEntities.B.Where(b => a.key == b.key && b.type == 1) 
          .Select(b => b.category).FirstOrDefault(), 
    size = ModelEntities.B.Where(b => a.key == b.key && b.type == 2) 
          .Select(b => b.category).FirstOrDefault(), 
    shape = ModelEntities.B.Where(b => a.key == b.key && b.type == 3) 
          .Select(b => b.category).FirstOrDefault(), 
} 

Ama muhtemelen böyle bir şey yapar EF-tasarımcı bazı fantezi varlık yaratmak gereken bir görünüm alışkanlığı oluşturmak aşağıdaki.