2010-12-29 26 views
26

LINQ sağlayıcısı ve yeni QueryOver sözdizimini kullanarak FluentNHibernate ve NH 3.0 ile oynuyorum. ŞimdiNHibernate 3.0: Hayır QueryOver ile FirstOrDefault()?

Result precedingOrMatchingResult = Session.QueryOver<Result>(). 
     Where(r => r.TimeStamp < timeStamp). 
     OrderBy(r => r.TimeStamp).Desc.     
     FirstOrDefault(); //get the preceding or matching result, if there is any 

, IntelliSense hiçbir olduğunu söylüyor:

Şimdi QueryOver ile ben belirli bir değere mümkün olduğunca yakın, ancak büyük olmadığı bir zaman damgası değerine sahip bir öğe (denilen sonuç) almak istiyorum FirstOrDefault() yöntemi gibi bir şey. Tabii ki, sıralı sorgularımı sıralayabilirim ve sonra öğemi almak için LINQ'u kullanabilirim. Ancak bu, tüm öğeleri önce belleğe yükler.

FirstOrDefault() için bir alternatif var mı, yoksa tamamen yanlış bir şey anladım mı?

+0

bak()'. Lütfen @RRR'nin cevabını kabul edin. –

cevap

10

NH3 entegre LINQ sağlayıcısı olan (:

+0

Harika görünüyor, Ben bir deneyin (sadece önümüzdeki yıl, şimdi kapalı olduğumdan beri!) – Marcel

+0

Bu hile yapar. Ancak, Where cümlelerinde, bazı ek kısıtlamalar olduğundan, LINQ to NH'nin NULL türlerine yönelik .HasValue() yöntem desteğini desteklemediğini buldum. Çok kötü, ama şimdi kontrol ediyorum! = Null çalışır. – Marcel

+8

Bu, QueryOver ile yapılan soruyu yanıtlamıyor. Cevap, sadece sorulan soru için geçerli değil. @ RRR'ler daha doğrudur. – Jafin

9

hiçbir değer Birinci veya Varsayılan yapar tür olarak ne olduğu, bulunursa

Result precedingOrMatchingResult = Session.QueryOver<Result>(). 
     Where(r => r.TimeStamp < timeStamp). 
     OrderBy(r => r.TimeStamp).Desc. 
     SetFetchSize(1). 
     UniqueResult(); 

UniqueResult veya null, tek bir değer dönecektir deneyin.

Getirme Boyutunu 1 olarak ayarlamak gerekli olabilir veya olmayabilir, bunu bir profiler ile test ederim.

Result precedingOrMatchingResult = Session.QueryOver<Result>(). 
     Where(r => r.TimeStamp < timeStamp). 
     OrderBy(r => r.TimeStamp).Desc. 
     Take(1).List(). //enumerate only on element of the sequence! 
     FirstOrDefault(); //get the preceding or matching result, if there is any 
+0

Ona bir göz attım. UniqueResult, SingleOrDefault'a benzer gibi görünüyor, ancak tek bir öğem yok. Bir listem var ve sadece ilk öğeyi seçmek istiyorum. – Marcel

+0

Sorgunun geri döndürülmesini istediğiniz şey yalnızca ilk öğedir, değil mi? Neden bir listeyi veritabanı sunucusundan döndürüyor ve sonra işin çoğunu atıyor? –

35

Artık çok gibi, bir listeye IQueryOver örneğinde Al() uzantısı yöntem ve sadece Numaralandır kullanabileceği bulduk sorgular dahili olarak HQL/SQL'ye çevrilir. Daha sonra NHibernate.Linq ad ve eklemek zorunda: SingleOrDefault `için

Result precedingOrMatchingResult = Session.Query<Result>(). 
    Where(r => r.TimeStamp < timeStamp). 
    OrderByDescending(r => r.TimeStamp). 
    FirstOrDefault(); 
+6

Yup. 'Take' önereceğim şey. Bunu RRR'nin 'List(). FirstOrDefault()' yerine 'SingleOrDefault' ile birleştirin ve mükemmel. –

+0

Aslında '.Take (1)', aynı sonucu sadece .SetFetchSize (1) 'i, SQL'e yalnızca bir sonuç istediğinizi söyleyeceği anlamında yapacak. Her iki durumda da, eşleşen tüm sonuçlar için bir sorgu yürütmüyorsunuz ve daha sonra birincisini numaralandırıyorsunuz. –

22
Result precedingOrMatchingResult = Session.QueryOver<Result>() 
              .Where(r => r.TimeStamp < timeStamp) 
              .OrderBy(r => r.TimeStamp).Desc 
              .SingleOrDefault(); 
+1

Evet, bu doğru cevap. 'SingleOrDefault()' –

+3

Neden NHibernate.NonUniqueResultException – Graham

+0

Benzersiz olmayan bir sonuç istisnası alıyorum. –

İlgili konular