2010-07-20 18 views
6

Pekala, hemen hemen aynı şeyi isteyen bazı mesajlar gördüm ama noktalar biraz farklıydı.NHibernate FlushMode Oto Yıkamadan Önce Kızarma

Bu klasik bir durumdur: Ben FlushMode = ile (/ bulmak/enumerable/vb kriterler kullanılarak), ben veritabanından onları almaya çalışıyorum AYNI OTURUM'da içinde, bir varlık güncellenmesi ve/saklıyorum Oto. Sorun: NHibernate, sorgulamadan önce güncellemeleri temizlemiyor, dolayısıyla veritabanından tutarsız veriler alıyorum.

"Fair enough", bazı insanlar dokümantasyon devletler olarak, diyecekler: bazı invokasyonlar arasında gelen

  • :

    floş Bu süreç, aşağıdaki noktalarda varsayılan olarak gerçekleşir (bul) ya da ISession.Flush dan NHibernate.ITransaction.Commit()

  • dan Enumerable()
  • ()

Cesur "bazı çağrılar" açıkça NH'nin hiç bir sorumluluğu olmadığını söylüyor. Doküman ayrıca devletler çünkü IMO olsa, burada bir tutarlılık sorunu olduğundan emin olun: explicity) (Flush, Oturum ADO.NET aramaları yürütür zaman konusunda kesinlikle hiçbir garanti, sadece sipariş olduğunda hariç

onlar idam edilir. Ancak, NHibernate, ISession.Find (..) yöntemlerinin eskiyen verileri hiçbir zaman döndürmeyeceğini garanti eder; Yanlış verileri de geri döndürmezler. Ben CreateQuery kullanıyorsam

Yani, mülkiyet Değeri = 20 ile varlıklar için ve filtreleme (yedek bul), NH may Değer = 30, ile DEĞİL dönüş kişiler değil mi? Ama aslında böyle bir şey oluyor çünkü Flush, gerektiğinde otomatik olarak gerçekleşmiyor. Sonuçta

public void FlushModeAutoTest() 
{ 
    ISession session = _sessionFactory.OpenSession(); 
    session.FlushMode = FlushMode.Auto; 

    MappedEntity entity = new MappedEntity() { Name = "Entity", Value = 20 }; 
    session.Save(entity); 

    entity.Value = 30; 
    session.SaveOrUpdate(entity); 

    // RETURNS ONE ENTITY, WHEN SHOULD RETURN ZERO 
    var list = session.CreateQuery("from MappedEntity where Value = 20").List<MappedEntity>(); 

    session.Flush(); 
    session.Close(); 
} 

: ben yanlış oluyor değilim, herkesin işini sağlamak için Flush aramak zorunda bir hata ya da sadece olmayan bir tahmin özelliği nedir?

Teşekkür ederiz.

Filipe

cevap

8

NHibernate kaynak kodu ile çok aşina değilim ama 2.1.2.GA açıklamasında ISession uygulanmasından bu yöntem soruya cevap verebilir:

/// <summary> 
/// detect in-memory changes, determine if the changes are to tables 
/// named in the query and, if so, complete execution the flush 
/// </summary> 
/// <param name="querySpaces"></param> 
/// <returns></returns> 
private bool AutoFlushIfRequired(ISet<string> querySpaces) 
{ 
    using (new SessionIdLoggingContext(SessionId)) 
    { 
     CheckAndUpdateSessionStatus(); 
     if (!TransactionInProgress) 
     { 
      // do not auto-flush while outside a transaction 
      return false; 
     } 
     AutoFlushEvent autoFlushEvent = new AutoFlushEvent(querySpaces, this); 
     IAutoFlushEventListener[] autoFlushEventListener = listeners.AutoFlushEventListeners; 
     for (int i = 0; i < autoFlushEventListener.Length; i++) 
     { 
      autoFlushEventListener[i].OnAutoFlush(autoFlushEvent); 
     } 
     return autoFlushEvent.FlushRequired; 
    } 
} 

O oto floş anlamına götür Sadece bir işlem içinde tutarlılığı garanti eder, bu da bazı anlam ifade eder. Testinizi bir işlem kullanarak yeniden yazmayı deneyin, bu sorunu çözecek olursa çok merak ediyorum.

+0

tks Tanrı, haklısın! :) Kod bloğu etrafında açık bir işlem kullanmak sorunu çözdü. Kriterleri kullanabilir, sorguları oluşturabilir, her neyse, değişiklik yapılır ve sorgu sonucu testi geçebilir. Tekrar teşekkürler! Dokümanları güncellemek için NH ekibine tavsiyede bulunacağım ve oto yıkama fonksiyonunun sadece açık bir işlem içinde çalıştığını ve bunun gelecekteki şüphelere yardımcı olacağını açıkça belirteceğim. – jfneis

+0

Rica ederim. Büyük soru, şimdiye kadar bunu hiç anlamadım. –

+0

Çok teşekkürler! Sorunumu çözdü. –

0

yönetme ve ayarlama hazırda bir artform olduğunu.

Neden başlangıç ​​değeri 20'yi ayarlıyorsunuz, kaydediyorsunuz, sonra da 30 olarak değiştiriyorsunuz?

Pratik olarak, oturumu değiştirmeye devam ediyorsanız, oturumu sorgulayın, bu işlemler arasında açık bir şekilde durmak isteyebilirsiniz. Hafif bir performans isabetiniz olabilir (sonuçta, oturumunuzu temizlemeyi en üst düzeye çıkarmanıza izin vermezsiniz), ancak sorun çıkarsa tekrar ziyaret edebilirsiniz.

"session.find yöntemlerinin asla eski veriler döndürmeyeceğini" belirttiniz. Çalıştığını görmek için kodunuzu createQuery yerine bulmak için değiştirirdim.

+0

Davranışı test etmek için ayar yapıyorum ve değiştiriyorum, gerçek kodum böyle görünmüyor. CreateQuery'yi kullanıyorum çünkü Bul, kullanımdan kaldırıldı ve CreateQuery, bunun yerine önerilenin yerini alıyor. – jfneis

2

Bunu düşünüyorsanız, örneğinizdeki sorgu her zaman db'ye gitmelidir. Oturum, db'deki tüm kayıtların tam bir önbelleği değildir. Yani , diskteki 20 değerine sahip diğer varlıklar olabilir. Ve işlem (veya) işlemi yapmadığınızdan(), oturumun NH hangi sorguyu sorgulamak istediğinizi bilmiyor (DB | Oturum). Bu "En iyi Uygulama" gibi görünüyor

açık işlemlerin iç (& setleri alır) her şeyi yapmaktır:

using(var session = sessionFactory.OpenSession()) 
using(var tx = session.BeginTransaction()) 
{ 
    // execute code that uses the session 
    tx.Commit(); 
} 

detaylar bir grup için here bakınız.

+0

oturumun tam bir veritabanı önbelleği olmadığına katılıyor ve açıkçası, NH DB'yi sorgulayacak ve başka kayıtlar olacak. İşte anlaşma geliyor: NH'nin dokümanı, NH'nin bu verileri seansla ilgileneceğini ve bunu otomatik olarak ** yapacağını söylüyor. Tx'i veya oturumu temizlemeyi taahhüt etmenin işe yarayacağını kabul ediyorum, ancak doktorların güncelliğini yitirdiğimizi söyleyebilir miyiz? Ya da bundan daha kötüsü: Bir kez çalıştığını anlayabilir miyiz, şimdi artık değil mi? – jfneis