2011-09-03 22 views
111

:LINQ To Varlıklar yöntemi tanımıyor Son. Gerçekten mi? Bu sorguda

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters 
     .OrderBy(p => p.ServerStatus.ServerDateTime) 
     .GroupBy(p => p.RawName) 
     .Select(p => p.Last()); 
} 

Ben

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters 
     .OrderByDescending(p => p.ServerStatus.ServerDateTime) 
     .GroupBy(p => p.RawName) 
     .Select(p => p.FirstOrDefault()); 
} 

çalışması için ben bile ilk sorgu ayna, p.First() kullanamadı bu onu geçmek zorunda kaldı.

Böyle sağlam bir ORM sisteminde niçin böyle temel sınırlamalar var? sınırlama nihayetinde SQL bu sorguyu çevirmek zorundadır gerçeğine aşağı gelir ve SQL bir SELECT BOTTOM (böyle bir şey) (T-SQL) bir SELECT TOP sahiptir ancak bu

+0

IEnumrable nesnesini yeni bir değişkene kaydedin, ardından variable.last() öğesini döndürün. Çalışacak. –

cevap

174

.

Sadece sırasına göre azalan ve daha sonra yaptığınız şey olan First()'u yapmanın kolay bir yolu var.

DÜZENLEME: Diğer sağlayıcılar muhtemelen muhtemelen bir şey olurdu Oracle üzerinde, SELECT TOP 1 farklı uygulamalarını olacak daha fazla gibi WHERE ROWNUM = 1

DÜZENLEME:

Başka az verimli bir alternatif - ben YAPMAYIN bunu tavsiye et! - .Last()'dan önce .ToList() numaralı veriyi aramak için, bu noktaya kadar oluşturulan LINQ To Varlıklar İfadesini hemen yürütecek ve ardından .Last() işlevi çalışacaktır, çünkü bu noktada .Last() etkin olarak çalıştırılacaktır. Bunun yerine, LINQ öğesinin Objects İfadesinin içeriği. (Ve belirttiğiniz gibi, binlerce kayıt ve atık yığınları CPU'yu asla kullanamayacak nesneler haline getirebilirdi)

Yine de, bu ikinciyi önermemenize gerek yok, ancak buradaki farkları göstermeye yardımcı oluyor ve LINQ ifadesi yürütüldüğünde. Eğer Linq bunu prefert eğer işler olacak gibi

+0

ve LINQ To SQL bu senaryo ile nasıl başa çıkıyor? – bevacqua

+1

@Nico: Aynı zamanda atıyor. – jason

+0

@Neil Evet Biliyorum, ToList'i arayabilirim, ancak veritabanından on binlerce kaydı filtrelemeyi tercih ederim. – bevacqua

12

bir Linq selektör tarafından OrderByDescending(x => x.ID).Take(1).Single()

şey Last() değiştirin: Yerine Last() ait

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters.OrderBy(p => p.ServerStatus.ServerDateTime).GroupBy(p => p.RawName).Select(p => p.OrderByDescending(x => x.Id).Take(1).Single()); 
} 
+0

Bu benim için mükemmel çalıştı. –

+1

.FirstOrDefault() yerine .Take (1) .Single() kullanmak için herhangi bir neden var mı? –

+1

@TotZam Geçerli bir yedek olacaktır: .First() Bu durumda, öğe sayısı tam olarak 1 değilse, Single() bir istisna atar. – MEMark

17

, bu deneyin:

model.OrderByDescending(o => o.Id).FirstOrDefault(); 
0

Yine de başka bir yol, OrderByDescending olmadan son öğeyi alır ve tüm varlıkları yükler:

dbSet 
    .Where(f => f.Id == dbSet.Max(f2 => f2.Id)) 
    .FirstOrDefault();