2012-12-28 19 views
5

aşağıdaki pseudoquery bir sorun haline çalıştırıyorum:iki benzer LINQ sorguları, bambaşka oluşturulan SQL

var daily = from p in db.table1 
      group p by new 
      { 
       key1, 
       key2 
      } into g 
      join d in db.table2 
      on new { p.key1, p.key2 } equals { d.key1, d.key2 } 
      select new 
      { 
       col1 = g.Key.key1 
       col2 = g.Sum(a => a.column2) 
       col3 = d.column3 
      }; 

O çalıştırır ama LINQ SQL Server gönderdiği oluşturulan SQL deyimi saçma olduğunu. Gerçek uygulama, her biri bir .Sum() hesaplaması olan 7 veya daha fazla sütunla yukarıdaki gibi benzer bir kurulum izler. Oluşturulan SQL, INNER JOIN olmadan 10-11 iç içe geçmiş SELECT deyimleri etrafında bir yere sahip ve tabii ki, sonsuza kadar sürecek.

Ben sorgunun başka uygulama dışarı test:

var daily = from p in 
       (from p in db.table1 
       group p by new 
       { 
        key1, 
        key2 
       } into g 
       select new 
       { 
        col1 = g.Key.key1, 
        col2 = g.Sum(a => a.column2) 
       }) 
      join d in db.table2 
      on new { p.key1, p.key2 } equals new { d.key1, d.key2 } 
      select new 
      { 
       col1 = p.col1, 
       col2 = p.col2, 
       col3 = d.column3 
      }; 

Bu sürüm, tek JOIN ALT SEÇ ve bir INNER deyimi ile çok daha makul SQL oluşturur (aynı zamanda yakın anında lanet çalışır). Bundan nefret ettiğim şey, ilk LINQ sorgusudur, IMHO, çok daha düz ve özlü iken, ikincisi ise tablo1'den iki kez istediğim tüm sütunları tanımlamak zorunda kaldığım için gereksizdir.

Bu iki benzer sorgu, sunucuda neden bu kadar farklı performans gösteriyor ve neden kod 2 çok daha az anlamlı olsa da, sorgu 2 neden çok daha verimli oluyor?

İlk sorguyu ikinci kadar verimli olarak yeniden yazmanın bir yolu var mı?

+0

Her iki sürümde SQL'i yükleyebilir misiniz? – usr

+0

@usr Sure, LINQ sorguları için yaptığım gibi ilk önce temizlemeyi deneyeyim. – Kittoes0124

+0

@Kittoes Linq yazmak ve Lambda ve SQL kodunu almak için [** LinqPad **] (http://www.linqpad.net/) kullanabilirsiniz – balexandre

cevap

6

LINQ 2 SQL aşağıdaki deseni ile sorunu olan:

from t in table 
group t by key into g 
from t in g //"ungroup" the grouping - this is causing a problem 
select ... 

Bence senin o tetikliyor katılmak çünkü "grubunu çözer" gruplama. LINQ birleşiminin, SQL'de temsil edilemez olan bir GroupJoin olduğunu unutmayın. Bir düşünün: Örnek sorgumu nasıl çevirirsiniz? table'a, table numaralı bir gruba, deli bir fazlalığa neden olmak için katılmalısınız.

Bu sorunu birkaç kez gördüm. Doğru çalışmayı buldunuz: Bu modelin oluşmasını önlemek için bir projeksiyonu zorlayın.

var daily = from p in db.table1 
      group p by new 
      { 
       key1, 
       key2 
      } into g 
      select new 
      { 
       col1 = g.Key.key1, 
       col2 = g.Sum(a => a.column2) 
      } into p 
      join d in db.table2 on new { p.key1, p.key2 } equals new { d.key1, d.key2 } 
      select new 
      { 
       col1 = p.col1, 
       col2 = p.col2, 
       col3 = d.column3 
      }; 

iç içe geçme daha az bilinen select x into y sözdizimi ile çıkarılır: biraz daha az zor sürümü vardır

.

+0

Lanet olsun, bunun cevabın olmadığını umuyordum. Ben gerçekten tüm tabloları 2 tablo2 dışında bir sütun almak için tablo1 iki sütunları tanımlamak zorunda nefret ediyorum. Ama sanırım konuyla ilgili herhangi bir seçeneğim var gibi görünmüyor. – Kittoes0124

+0

@Kittoes da bu konuda benim hislerim. Öte yandan LINQ, bu kötü kenar durumlarını tolere etmeye değecek kadar çok çalışma kaydeder. EF takımının yetkili LINQ desteği vermesini veya L2S'nin terk edilmemesini diliyorum ... – usr

+1

Elbette. LINQ'in kaydettiği diğer işlerin miktarı kesinlikle gülünç olduğu için, böyle bir şey olduğunda kesinlikle hoşgörülü olmaya değer.Sadece gerçek bir sebepten ötürü 10 sütun + iki kere tanımlayan çıldırtıcı beni tahrik eder. NEDEN olduğunu açıkladığınız için çok teşekkür ederim. – Kittoes0124