2010-11-18 15 views
3

aşağıdaki gibi bir sınıf var:LINQ sürümü, bir dizi sürümden en son ürünü seçmek için neler bulunuyor?

public class Invoice 
{ 
    public int InvoiceId {get;set;} 
    public int VersionId {get;set;} 
} 

bir Invoice değiştirilir Her seferinde, VersionId artırılır alır, ancak InvoiceId aynı kalır.

InvoiceId VersionId 
1   3 
2   2 

yani: Sadece sonuçlar alabilirsiniz nasıl

InvoiceId VersionId 
1   1 
1   2 
1   3 
2   1 
2   2 

: Yani şu sonuçları olan bir IEnumerable<Invoice> verilen En son VersionId'ye sahip olan sonuçlardan sadece Faturaları istiyorum. Bunu T-SQL'de kolayca yapabilirim, ancak yaşamımın doğru LINQ sözdizimini kullanamaması. İlk önce Varlık Çerçevesi 4 Kodunu kullanıyorum.

+0

Bunu her zaman yapmanız gerekiyorsa, bunun yerine seçebileceğiniz, maddi veya dizin oluşturulmuş bir görünüme sahip olmanız en iyisi olabilir. Daha hızlı olabilir ve baş ağrısını yoldan çıkarabilir. – Juliet

cevap

1

al, InvoiceId grup onları, daha sonra her grubun ilk sonucu almak.

var query = list.OrderByDescending(i => i.VersionId) 
       .GroupBy(i => i.InvoiceId) 
       .Select(g => g.First()); 

EDIT: Bu deneyin Max kullanarak nasıl bu yaklaşımdan?

var query = list.GroupBy(i => i.InvoiceId) 
       .Select(g => g.Single(i => i.VersionId == g.Max(o => o.VersionId))); 

Single iyi niyeti gösteriyor rağmen aynı sonucu verecek ... yanı Single yerine FirstOrDefault veya SingleOrDefault kullanmayı deneyin.

+0

Bu, EF'ye karşı çalışmıyor gibi görünüyor, tüm öğeleri döndürüyor. – GenericTypeTea

+0

@GenericTypeTea EF çok aşina değilim. İkinci yaklaşımımı deneyebilir misin? –

+0

@Ahmad - Sanırım işe yarayabilirdi, ancak hatalı sonuçların sayısını tahmin ettim. Şimdi evdeyim, bu yüzden sabah tekrar deneyeceğim. – GenericTypeTea

1

DÜZENLEME: Bu sorguları LINQ ile Varlıklara test ettim. Çalışıyor gibi görünüyorlar, bu yüzden sorun başka bir şey olabilir mi?


Seçenek 1:

var latestInvoices = invoices.GroupBy(i => i.InvoiceId) 
          .Select(group => group.OrderByDescending(i => i.VersionId) 
                .FirstOrDefault()); 

DÜZENLEME: Değiştirilen 'Son' 'FirstOrDefault' için, LINQ varlıkları için 'Last' sorgu operatörü ile sorunları vardır.


Seçenek 2: VersionId tarafından

var invoices = from invoice in dc.Invoices 
       group invoice by invoice.InvoiceId into invoiceGroup 
       let maxVersion = invoiceGroup.Max(i => i.VersionId) 
       from candidate in invoiceGroup 
       where candidate.VersionId == maxVersion 
       select candidate; 
+0

Tamam, şimdi gerçek uygulamasında test ediyorum. – GenericTypeTea

+0

"XYZ" türünde sabit bir değer oluşturulamıyor. Bu bağlamda yalnızca ilkel türler ('Int32, String ve Guid' gibi) destekleniyor. " EntityFramework kullanırken. – GenericTypeTea

+0

Üzgünüm, sadece LINQ to SQL ile test ettim. – Ani

1

Benim versiyon:

olarak yorumlarda Ahmed tarafından sözü edilen

var h = from i in Invoices 
     group i.VersionId by i.InvoiceId into grouping 
     select new {InvoiceId = grouping.Key, VersionId = grouping.Max()}; 

Güncelleme yukarıdaki sorgu bir projeksiyon dönecektir. Aşağıdaki sürüm bir IQueryable<Invoice> döndürecektir. Sorguyu oluşturmak için kompozisyon kullanıyorum çünkü daha açık olduğunu düşünüyorum.

+1

Bu, mevcut "Fatura" nesnelerini kullanmak yerine anonim bir türe dönüştürülür. Ani ve ben 'Max' kullanmayı ve her iki sorguda ve akıcı sözdiziminde orijinal nesnelerini sürdürmeyi gösteriyorum. –

+0

@Ahmad Mageed: Doğru, ancak OP'nin gereksinimlerini hala yerine getirebilir. EntitySet'i döndürecek başka bir sürüm ekledim. – Sorax

İlgili konular