2017-08-07 60 views
1

它看起來每個I查詢一些與LINQ NHibernate的時間一樣從頭開始構建該查詢:如何緩存編譯的LINQ查詢(不是結果)?

dotTrace report

代碼看起來像

session.Query<User>().Where(x => ids.Contains(x.Id)).ToFuture(); 

是否有可能避免重新編譯呢?

關於緩存QueryOver/Criteria查詢的相同問題(不是很重要,但它可能仍然適合範圍)。

+0

@stybl「重用LINQ查詢」和「重用LINQ到數據庫NH查詢」是不一樣的東西 – Vlad

+0

我知道,這就是爲什麼我撤回了近距離投票。雖然忘記了評論。 – stybl

+1

https://stackoverflow.com/a/4817010/1162077 –

回答

0

特別是這種情況下被接入到IDS(int[])造成這裏

session.Query<User>().Where(x => ids.Contains(x.Id)).ToFuture(); 

轉化MemberAccessExpression(不ConstantExpression)和NHibernate不得不對其進行評估。儘管ids從未被更改過,但它仍被捕獲到一個關閉生成的類中(如DisplayClass<>.ids)。

我通過製作PartialEvaluatingExpressionTreeVisitor我自己的版本優化,這種情況下:

protected Expression EvaluateSubtree(Expression subtree) 
    { 
     ArgumentUtility.CheckNotNull(nameof(subtree), subtree); 
     var memberExpression = subtree as MemberExpression; 
     if (memberExpression != null) 
     { 
      Expression constant; 
      if (TryEvaluateMember(memberExpression, out constant)) return constant; 
     } 

     if (subtree.NodeType != ExpressionType.Constant) 
      throw new NHibernateExpressionOptimizerException(subtree); 
     ConstantExpression constantExpression = (ConstantExpression)subtree; 
     IQueryable queryable = constantExpression.Value as IQueryable; 
     if (queryable != null && queryable.Expression != constantExpression) 
      return queryable.Expression; 
     return constantExpression; 
    } 

    bool TryEvaluateMember(MemberExpression memberExpression, out Expression constant) 
    { 
     constant = null; 
     ConstantExpression c = memberExpression.Expression == null ? Expression.Constant(null) : EvaluateSubtree(memberExpression.Expression) as ConstantExpression; 
     if (c == null) return false; 
     var fieldInfo = memberExpression.Member as FieldInfo; 
     if (fieldInfo != null) 
     { 
      constant = Expression.Constant(ReflectorReadFieldDelegate(fieldInfo, c.Value)); 
      return true; 
     } 

     var propertyInfo = memberExpression.Member as PropertyInfo; 
     if (propertyInfo != null) 
     { 
      constant = Expression.Constant(ReflectorReadPropertyDelegate(propertyInfo, c.Value)); 
      return true; 
     } 
     return false; 
    } 

反射器代表使用一種緩存Reflection.Emit的魔力。

+0

這聽起來像改變了我一般不喜歡的默認行爲。爲什麼不把它包裝在一個方法調用中,如公共靜態T ToConst (T item){return item;},然後將該邏輯用於該方法調用?它給你更多的靈活性,更清楚你的意圖是什麼,不是嗎? – MBoros