2012-07-05 85 views
0

使用NHibernate進行條件查詢時,我想從緩存中獲取新的結果而不是舊的結果。重複查詢不會刷新返回對象的屬性

的方法基本上是:

  1. 查詢持久對象到NHibernate的應用。
  2. 從外部更改數據庫條目(另一個程序,SSMS/MSSQL中的手動編輯等)。
  3. 查詢持久化對象(使用相同的查詢代碼),以前加載的對象應從數據庫中刷新。

下面的代碼(略有改變對象名稱):

public IOrder GetOrderByOrderId(int orderId) 
{  
... 
IList result; 
var query = 
    session.CreateCriteria(typeof(Order)) 
     .SetFetchMode("Products", FetchMode.Eager) 
     .SetFetchMode("Customer", FetchMode.Eager) 
     .SetFetchMode("OrderItems", FetchMode.Eager) 
     .Add(Restrictions.Eq("OrderId", orderId)); 
query.SetCacheMode(CacheMode.Ignore); 
query.SetCacheable(false); 

result = query.List(); 
... 
} 

的SetCacheMode和SetCacheable已經被我添加禁用緩存。此外,NHibernate的出廠設置與配置參數UseQueryCache =假:

Cfg.SetProperty(NHibernate.Cfg.Environment.UseQueryCache, "false"); 

不管我做什麼,包括把/刷新緩存模式,查詢或會話:NHibernate的保持返回我的過期對象第二次查詢被調用,沒有外部提交的更改。 Info btw:這種情況下的過期值是Version列的值(以測試在保存之前是否可以檢測到過時的對象狀態)。但是由於多種原因,我需要新的查詢結果!

NHibernate甚至會生成一個SQL查詢,但它永遠不會用於返回的值。保持會話打開只需要在髒列上進行動態更新(也沒有解決方案的無狀態會話!);我不想在代碼中的任何地方添加Clear(),Evict()等,特別是因爲查詢位於較低級別,並且不記得先前加載的對象。悲觀鎖定會導致性能下降(多用戶環境!)

有沒有辦法強制NHibernate通過配置直接向數據庫發送查詢並獲得最新結果,而不使用不需要的緩存功能?

回答

1

首先:這沒有什麼做二級緩存(這是什麼SetCacheModeSetCacheable控制)。即使這樣做,那些控制緩存查詢,而不是緩存返回的實體。

當一個對象已經被加載到當前會話(也稱爲「第一級緩存」的一些人,雖然它不是一個緩存,但一個Identity Map),再從數據庫中使用任何方法從未查詢將覆蓋其值。

這是通過設計,它有很好的理由這樣做。

如果您需要使用查詢更新多個記錄中可能更改的值,那麼您以前的必須爲Evict。您也可以閱讀Stateless Sessions

0

此代碼是否在事務中運行?或者是在事務中運行的外部進程?如果其中一個仍在交易中,您將看不到任何更新。

如果情況並非如此,那麼您可能能夠在NHibernate創建的日誌消息中找到問題。這些信息非常豐富,並會一直告訴你它到底在做什麼。

保持會話開放時,只需要做骯髒列動態更新僅

這既是問題,或將成爲未來的一個問題。 NHibernate正在盡一切努力使自己的生活變得更好,但是你正在努力盡可能的去阻止NHibernate正確地完成工作。

如果您希望NHibernate只更新髒列,您可以查看類映射文件中的dynamic-update-attribute