Entity Framework 4 Single () - First () - FirstOrDefault ()


119

Tek bir öğeyi sorgulamanın farklı yollarının ve her birinin ne zaman kullanılacağının bir karşılaştırmasını bulmaktan büyük keyif alıyorum.

Herhangi birinin tüm bunları karşılaştıran bir bağlantısı veya birini diğerine niçin kullanacağınıza dair hızlı bir açıklaması var mı? Hala bilmediğim daha fazla operatör var mı?

Teşekkür ederim.

Yanıtlar:


205

İşte farklı yöntemlere genel bir bakış:

  • Bul () - birincil anahtara göre bir öğe almak istediğinizde. Bu, bir öğe bulamazsa boş döndürür. Veritabanına gitmeden önce bağlama bakacaktır (yorumlarda Yaron'un belirttiği gibi), aynı içerik canlıyken aynı varlığı birden çok kez almanız gerekiyorsa önemli bir verimlilik faktörü olabilir.

  • Tek () - bir sorgu tarafından tam olarak bir öğe döndürülmesini beklediğinizde. Bu, sorgu tam olarak bir öğe döndürmezse bir istisna oluşturur.

  • SingleOrDefault () - bir sorgu tarafından sıfır veya bir öğe döndürülmesini beklediğinizde (yani, belirli bir anahtara sahip bir öğenin var olup olmadığından emin değilsiniz). Bu, sorgu sıfır veya bir öğe döndürmezse bir istisna oluşturur.

  • İlk () - bir veya daha fazla öğenin bir sorgu tarafından döndürülmesini beklediğinizde, ancak yalnızca kodunuzdaki ilk öğeye erişmek istediğinizde (buradaki sorguda sıralama önemli olabilir). Bu, sorgu en az bir öğe döndürmezse bir istisna oluşturur.

  • FirstOrDefault () - bir sorgu tarafından sıfır veya daha fazla öğe döndürülmesini beklediğinizde, ancak yalnızca kodunuzdaki ilk öğeye erişmek istediğinizde (yani, belirli bir anahtara sahip bir öğenin mevcut olup olmadığından emin değilseniz)


1
Senaryoya göre değişir. Her zaman db'den tek bir kaydı geri almanız gerektiğini biliyorsanız, belirli bir sorgu için ne fazla ne de az, o zaman kullanmak için 'doğru' olan Single () 'dır. Diğer durumlarda diğerleri daha uygun olabilir. EF'in önceki sürümlerinde, tek bir kayıt beklediğiniz senaryolar için çalışan First () ve FirstOrDefault () ile sınırlıydık, ancak gerçekte tek bir kayıttan fazlasını geri alırsanız sizi uyarmazlar, bu da bağlı olarak önemli olabilir durum.
Steve Willcock

1
Teşekkürler. Artık Single () 'ın daha iyi olmayacağı First ()' e ihtiyaç duyduğumu göremiyorum. Daha az yoğun olsaydım, First () 'ü hala ne zaman kullanacağımı takdir edebileceğime / anlayabileceğime eminim.
asfsadf

1
İlk (), yalnızca sipariş verdiğiniz şeyin en yüksek veya en düşük değerine sahip nesneyi almak istediğiniz durumda en mantıklıdır. Örneğin, bana toplam değeri en yüksek olan satışı bulun. Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain

5
Buradaki tüm yorumlar önemli bir fark olarak görünüyor. Find (), db'ye basmadan önce bağlamı arayan tek yöntemdir.
Yaron Levi

5
Bir SQL veri tabanı sorgulama Bir başka nokta Singleya SingleOrDefaultda 2 kayıtları (sınır 2) için sorgular Firstveya FirstOrDefault1 (sınırı 1) için sorgular.
Bart Calixto

22

Ben her zaman kullanma eğilimindeyim FirstOrDefault. Gerçekten performans konusunda seçici olmak istiyorsanız, o zaman FirstOrDefaultEF'de kullanmalısınız . Kapakların altında, SingleOrDefaultsorguda top (2) kullanılır, çünkü kriterlere uyan ikinci bir satır olup olmadığını kontrol etmesi gerekir ve eğer varsa, bir istisna atar. Temel olarak SingleOrDefault, sorgunuz 1'den fazla kayıt döndürürse bir istisna atmak istediğinizi söylüyorsunuz.


5
Hiç anlamlı olacak FirstOrDefaultve arasındaki performans farkını SingleOrDefaultölçtünüz mü? Çoğu durumda erken optimizasyon olduğunu söyleyebilirim.
Steven

Kullanmaya meyilliyim Single()veya sadece bir tane olması gereken birSingleOrDefault() şeyi iade ettiğimde . Bunu yapmamın nedeni, hatalı yazılmış sorgular yaparak hataları tespit etmektir, olması gerekenden daha fazlasını döndüren, başarısız olur. En azından aklımda bu, sistemdeki verilerin tutarlı kalmasına yardımcı olacaktır. Tabii ki bu daha yavaş, ama çok daha yavaş olmadığını tahmin ediyorum ve bu bedeli ödemeye hazırım.
mortb

15

Gerçekten çok basit: Singletek bir öğe döndürür ve birden fazla öğe yoksa veya hiç yoksa bir istisna oluşturur. Firstilk öğeyi iade edecek veya öğe olmadığında atacaktır. FirstOrDefaultöğe olmadığında ilk öğeyi döndürür veya varsayılan değeri ( nullverilen türün bir başvuru türü olması durumunda) döndürür .

API'nin sahip olması gereken davranış budur. Bununla birlikte, temeldeki uygulamanın farklı bir davranışa sahip olabileceğini unutmayın. Entity Framework buna uyarken, LLBLGen gibi bir O / RM null, arama sırasında geri dönebilir Firstki bu çok garip bir şeydir. Bu, tasarımcı IMO'nun çok garip (ve inatçı) bir karardı.


Teşekkürler Steven. Sanırım hala neden birini diğerine tercih ettiğini merak ediyorum? Her zaman FirstOrDefault () 'yu kullandım ve neden gördüğüm birçok yeni örneğin Single ()' a geçtiğini merak ediyordum. Single () 'a geçmek için bir neden var mı? Aynı şeyi başaran, onun yerine dikkate almam gereken başkaları var mı?
asfsadf

7
Kodunuzun "hızlı başarısız" olmasını istiyorsanız, First () ve Single (), kodunuzun bekleneni daha kesin bir şekilde söylemesine izin verin (aksi takdirde başarısız olabilir)
Frank Schwieterman

3
Frank'e tamamen katılıyorum. Aynı zamanda amacı iletmekle de ilgilidir. Singleaçıkça, sonucun yalnızca bir öğeye sahip olmasını beklediğinizi ifade eder.
Steven

8

Dört yöntemin her birinin yeri vardır; Gerçi gerçekten sadece iki farklı operasyonunuz var.

  • İlk - Birden çok öğe içeren bir sonuç kümesi beklediğinizde, o kümedeki ilk öğeyi bana verin.
  • Tek - Tek bir sonuç beklerken, o öğeyi bana ver.

XxxxOrDefault () sürümü "Boş bir sonuç kümesinin istisnai bir durum olduğunu düşünmek istemiyorum" u ekler.


Tamam, bana öyle geliyor ki First () nadiren işe yarardı. Single () 'ın ilk seçenek olmayacağı bir senaryo bulmakta zorlanıyorum. Şans eseri, hızlı bir elin mi var? Teşekkürler.
asfsadf

3
Maalesef pek çok geliştirici First () veya FirstOrDefault () 'u yalnızca savunma önlemi olarak kullanıyor ve gerçek sorunları gizleme potansiyeline sahip olduğunda bunun bir istisnadan kaçınacağını düşünüyor.
Matt H

3

Öte yandan, bu yöntemleri aşağıdaki gibi temel mantığa bölebilirsiniz:

  • Yöntem, veritabanını doğrudan sorgulayacak : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • Yöntem, sorguyu veritabanına karşı yayınlamadan önce önbellekte bir arama gerçekleştirir : Find ()

Bazı performans ayrıntıları için, özellikle ikinci durumda, buraya bakabilirsiniz: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Ek olarak, ilk grupta karmaşık sorgular tanımlayabilirsiniz, ancak Find () yöntemi ile arama için yalnızca varlık anahtarı sağlayabilirsiniz.


0

Single () ve SingleOrDefault () genellikle kimlikler gibi benzersiz tanımlayıcılarda kullanılırken, First () veya FirstOrDefault () genellikle birden çok sonuca sahip olabilecek ancak yalnızca "İlk 1" i isteyen bir sorgu için kullanılır .

Single () veya First () , sonuç döndürülmezse bir istisna atar, SingleOrDefault () ve FirstOrDefault () istisnayı yakalar ve null veya varsayılan (ResultDataType) döndürür.

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.