2017-08-07 7 views
1

それは私がLINQのNHibernateで何かを照会するたびに、最初からそのクエリを構築するようになっていますコンパイル済みLINQクエリ(結果ではない)をキャッシュするにはどうすればよいですか?

dotTrace report

コードが

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

のように見えるが、それを再コンパイルを回避することが可能ですか?

また、QueryOver/Criteriaクエリをキャッシュすることに関する同じ質問(それほど重要ではありませんが、依然として有効範囲に収まるかもしれません)。ここでは特に、この場合は、そのことにより、IDS(int[])へのアクセスが発生した

+0

@stybl "LINQクエリを再利用する"と "LINQをデータベースNHクエリーに再利用する"は同じではありません – Vlad

+0

私はクローズ投票を撤回した理由を認識しています。しかし、コメントについて忘れてしまった。 – stybl

+1

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

答えて

0

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

これは私が一般的に好きではないデフォルトの動作を変更するように思えます。 public static T ToConst (T item){return item;}のようなメソッド呼び出しでラップして、そのメソッド呼び出しにロジックを適用するのはなぜですか?それはあなたにより柔軟性を与え、あなたの意図は何か、より明確です。 – MBoros

関連する問題