2012-01-05 45 views
6

給出一個簡單的投影像下面,NHibernate的將緩存查詢計劃,而不是更新變量的值時,查詢是相同的:LINQ的投影正在NHibernate的不正確緩存3.2

int argValue = 1; 
    var result1 = database.Users.Select(x => new {x.Name, BadArg = argValue}).First(); 

    argValue = 2; 
    var result2 = database.Users.Select(x => new {x.Name, BadArg = argValue}).First(); 

預期

RESULT1值將是名稱= 「鮑勃」 和BadArg = 1

RESULT2值將名稱= 「鮑勃」 和BadArg = 2

實際

RESULT1值將是NAME = 「鮑勃」 和BadArg = 1

RESULT2值將是NAME = 「鮑勃」 和BadArg = 1

顯然,這會導致大量的瘋狂的行爲,如果你不期待它。我在NHibernate的bug跟蹤中看到了類似於couple bug reportscouple bug reports,但自去年5月以來沒有任何操作。所以要麼沒有人使用Linq到Nhibernate,要麼有一些我不知道的解決方法。

在我深入研究NHibernate源代碼之前,有沒有辦法禁用查詢計劃緩存來防止此行爲或其他解決方法,或者是否有人從上述鏈接應用了修補程序?

注意

的例子是爲了保持簡單的問題,在現實中我有我想保持作爲一個IQueryable一個複雜的推算,過早地轉化爲一個IEnumerable將無法正常工作。

更新 是否在github上掌握了NHibernate的3.2.1

+0

我一直在尋找這個好奇心,它看起來像問題不是NHibernate的緩存本身,它是Linq表達式樹緩存。問題是,表達式樹被簡化了,變量引用簡化爲一個常量表達式,之後緩存鍵被構造 - 但那時候並沒有告訴範圍變量ref和常量之間的區別。 : -/ – Rytmis 2012-01-15 19:13:04

+0

我也一直有這個問題,這是一個浪費時間。每隔幾個月它就會恢復原狀,我已經忘記了它,只是爲了再次發現它。在我的情況下,我不是投射到匿名對象,而是爲我自己創作的對象賦值。 – 2012-06-01 19:04:36

回答

0

如果你想完全避免緩存不行,請嘗試更改您的代碼如下:

int argValue = 1; 
var result1 = database.Users.AsEnumerable().Select(x => new {x.Name, BadArg = argValue}).First(); 

argValue = 2; 
var result2 = database.Users.AsEnumerable().Select(x => new {x.Name, BadArg = argValue}).First(); 

什麼情況是,而不是使用NHLinq Select方法,你最終會使用System.Linq Select方法 - 有效地防止NHibernate緩存投影。當然,缺點是你會在內存中進行投影,所以你最終會從你的用戶表中選擇所有的字段,而不是你想要的。

+0

我知道這樣做會起作用,但會有點失敗。我的例子對於這個問題很簡單,但實際上我想保留它作爲IQueryable。 – 2012-01-06 00:02:29

0

以下是如何關閉一級緩存: http://darioquintana.com.ar/blogging/2007/10/08/statelesssession-nhibernate-without-first-level-cache/

我不認爲你可以禁用二級緩存,但我覺得你不必爲這個問題。

(從本質上講,你需要創建和銷燬每個查詢的會話。)

如果發現問題仍然持續,雖然,你必須做什麼Rytmis建議。

+0

好的建議! :-) – Rytmis 2012-01-05 23:35:34

+0

僅僅爲了執行查詢而創建不同的會話似乎有點沉重,並且可能對來自另一個會話的對象產生不良後果。 – 2012-01-06 00:06:03

+0

取決於你的預測 - 如果你的投影只包含標量值,它應該不成問題。但你說得對,它感覺不對。 – Rytmis 2012-01-06 08:10:37