LINQ To Entities, Last yöntemini tanımıyor. Gerçekten mi?


144

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

Çalışması için bunu buna değiştirmek zorunda kaldım

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

p.First()İlk sorguyu yansıtmak için bile kullanamadım .

Aksi halde bu kadar sağlam bir ORM sistemi olan şeyde neden böyle temel sınırlamalar var?


IEnumrable nesnenizi yeni bir değişkene depolayın ve daha sonra variable.last () öğesini döndürün. Çalışacak.
Ali.Rashidi

Yanıtlar:


220

Bu sınırlama, sonunda bu sorguyu SQL ve SQL'e çevirmek zorunda olduğu gerçeği ile ilgilidir SELECT TOP(T-SQL'de), ancak SELECT BOTTOM(böyle bir şey yok).

Etrafında kolay bir yol var, sadece azalan sipariş verin ve sonra yaptığınız First()şey budur.

EDIT: Diğer sağlayıcılar muhtemelen farklı uygulamaları olacak SELECT TOP 1, Oracle üzerinde muhtemelen daha benzer bir şey olurduWHERE ROWNUM = 1

DÜZENLE:

Başka bir daha az verimli alternatif - bunu tavsiye ETMEM! - daha .ToList()önce verilerinizi çağırmaktır .Last(), bu da o noktaya kadar oluşturulmuş olan LINQ To Entities İfadesini hemen yürütür ve sonra .Last () öğeniz çalışır, çünkü bu noktada .Last()bir Bunun yerine Nesne İfadesi için LINQ . (Ve belirttiğiniz gibi, hiç kullanılmayacak binlerce kayıt ve atık CPU yükü nesnesini geri getirebilir)

Yine, bu ikinci yapılmasını tavsiye etmem, ancak LINQ ifadesinin nerede ve ne zaman yürütüldüğü arasındaki farkı göstermeye yardımcı olur.


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

@Neil evet ToList'i arayabileceğimi biliyorum, ancak veritabanına binlerce kayıt almayı tercih etmiyorum, onları sadece beş kayda filtrelemek için
bevacqua

2
Sorgunuzun küçük sonuçlar getireceğini biliyorsanız, arama ToListo kadar da kötü değil.
Justin Skiles

35

Bunun yerine şunu Last()deneyin:

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

14

Last()Bir Linq seçici ile değiştirinOrderByDescending(x => x.ID).Take(1).Single()

Linq'de yapmayı tercih ederseniz böyle bir şey işe yarar:

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

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

2
@TotZam Geçerli değiştirme .First () olurdu, çünkü öğe sayısı tam olarak 1 değilse Single () bir istisna atar.
MEMark

0

Başka bir yol ise OrderByDescending olmadan son öğeyi almak ve tüm varlıkları yüklemek:

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

0

Çünkü LINQ to Entities (ve genel olarak veritabanları) tüm LINQ yöntemlerini desteklemez (ayrıntılar için buraya bakın: http://msdn.microsoft.com/en-us/library/bb738550.aspx )

Burada ihtiyacınız olan şey, verilerinizi "son" kayıt "önce" olacak ve daha sonra FirstOrDefault'u kullanabileceğiniz şekilde sipariş etmektir. Veritabanlarının genellikle "ilk" ve "son" gibi kavramları olmadığını, en son eklenen kaydın tabloda "son" olacağı gibi olmadığını unutmayın.

Bu yöntem sorununuzu çözebilir

db.databaseTable.OrderByDescending(obj => obj.Id).FirstOrDefault();

-2

AsEnumerable()Seçim işlevinden önce tek bir işlev eklemek benim için çalıştı.
Misal:

return context.ServerOnlineCharacters
    .OrderByDescending(p => p.ServerStatus.ServerDateTime)
    .GroupBy(p => p.RawName).AsEnumerable()
    .Select(p => p.FirstOrDefault());

Ref: https://www.codeproject.com/Questions/1005274/LINQ-to-Entities-does-not-recognize-the-method-Sys


Çalışma kodunu bağlantıdan cevabınıza dahil etmeniz önerilir. Yalnızca bağlantıya verilen yanıtlar olumsuz ilgi çekecektir. Lütfen sorunu çözmek ve çözmek için bulduğunuz kodu ekleyerek tam bir yanıt verin. Bu, gelecekte 404 hataları nedeniyle çalışmayan bağlantılar sorununu çözer.
Studocwho


Bu cevabın aşağı tarafı, "AsEnumerable" sunucu tarafından önce tüm sonuçları getirip ilkini seçmesidir. Bu çok istenmeyen bir durum olabilir. (Sunucu tarafında getirilen 20k + kayıtları nedeniyle sonuçların 20+ saniye sürdüğü böyle bir durum vardı, bir kez DB tarafına geri döndüğümde, sonuçlar bir saniyeden daha kısa sürede geri döndü)
TChadwick
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.