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の魔法のようなものを使用します。
@stybl "LINQクエリを再利用する"と "LINQをデータベースNHクエリーに再利用する"は同じではありません – Vlad
私はクローズ投票を撤回した理由を認識しています。しかし、コメントについて忘れてしまった。 – stybl
https://stackoverflow.com/a/4817010/1162077 –