2012-08-03 95 views
3

我有NHibernate的二級緩存問題。當我使用查詢時:LINQ到NHibernate和動態LINQ - 查詢緩存不起作用

 var items1 = Session.Query<Row>() 
      .Cacheable(); 
      .Fetch(x => x.Field) 
      .OrderBy(x => x.Field.Value) 
      .ToList(); 

一切都很好 - 查詢被緩存。但是,當我想用​​動態的LINQ(a link):

 var items2 = Session.Query<Row>() 
      .Cacheable(); 
      .Fetch(x => x.Field) 
      .OrderBy("Field.Value") 
      .ToList(); 

查詢不被緩存。有趣的是,當我刪除代碼行時:

  .Fetch(x => x.Field) 

緩存再次工作。所以問題是一起使用Fetch和動態linq OrderBy方法。

編輯:

當我嘗試做調試NH代碼(QueryKey類),調試器告訴我,這兩個查詢不具有相同的使用ResultTransformer(更深:一個listTransformation私有實例)。

任何想法?

Chris

+0

您使用的是什麼版本的NH? – hazzik 2012-08-03 12:21:49

+0

NHibernate 3.3.1.4000 – cryss 2012-08-03 12:28:45

+0

也許NH確定查詢有問題。我不知道NH如何存儲用於比較和從緩存加載的查詢標識符(整個SQL?)。但是當我比較第一個和第二個示例中的ExpressionTree(在調用ToList之前)時,它們是相同的。 – cryss 2012-08-03 13:18:24

回答

2

好的,我知道是什麼原因。

動態Linq不使用Linq表達式中的參數名稱。例如。如果我想使用lambda衆所周知聲明進行排序,我寫:

query.OrderBy(item => item.Name) 

上面我們看到的item拉姆達參數名稱。

當我使用動態LINQ:

query.OrderBy("Name") 

在結果可查詢中的OrderBy mehod拉姆達參數沒有名稱(如item上面寫)。我們可以說明結果是這樣的:

query.OrderBy(=> .Name) 

而現在,當NHibernate的被解碼時可查詢的表達,發現有一個沒有名稱的表達式參數,NH給它使用GUID類隨機名稱。因此,每個使用動態LINQ的排序都會產生一個具有不確定lambda參數的可查詢表達式。這就是爲什麼NHibernate認爲:query.OrderBy("Name")query.OrderBy("Name")不一樣 - 他們每次都從頭開始生成另一個lamda參數。

SOLUTION

如果你要修復它,你必須修改動態的LINQ庫。

  1. 在方法變更線:

    if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name)) 
    

    到:

    if (parameters.Length == 1 && (parameters[0].Name == "it" || String.IsNullOrEmpty(parameters[0].Name))) 
    
  2. 在方法DynamicQueryable.OrderBy變更線:

    Expression.Parameter(source.ElementType, "") 
    

    到:

    Expression.Parameter(source.ElementType, "it") 
    

現在,query.OrderBy("Name")會產生query.OrderBy(it => it.Name)

乾杯!

+2

對於任何磕磕絆絆的人來說,這個問題在NHibernate 3.3.2中得到解決。 – 2012-10-30 19:03:46