我对NHibernate的二级缓存有问题。当我使用查询时:
var items1 = Session.Query<Row>()
.Cacheable();
.Fetch(x => x.Field)
.OrderBy(x => x.Field.Value)
.ToList();
一切都很好 - 查询被缓存。但是当我想使用Dynamic 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私有实例)。
有什么想法吗?
克里斯
答案 0 :(得分:2)
好的,我知道是什么原因。
Dynamic Linq在Linq表达式中不使用参数名称。例如。如果我想使用lambda statemant进行排序,我写道:
query.OrderBy(item => item.Name)
上面我们看到item
lambda参数名称。
当我使用Dynamic linq时:
query.OrderBy("Name")
在结果Queryable中,OrderBy mehod中的lambda参数没有名称(如上面所写的item
)。我们可以这样说明结果:
query.OrderBy( => .Name)
现在,当NHibernate解码那个Queryable表达式并找到一个没有名称的表达式参数时,NH使用GUID类给它一个随机名称。因此,使用动态linq的每个排序都会产生一个具有不稳定lambda参数的可查询表达式。这就是为什么NHibernate认为:query.OrderBy("Name")
和query.OrderBy("Name")
不相同的原因 - 他们每次都从头开始生成另一个lamda参数。
<强>解强>
如果要修复它,则必须修改Dynamic Linq库。
在方法ExpressionParser.ProcessParameters
更改行:
if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name))
为:
if (parameters.Length == 1 && (parameters[0].Name == "it" || String.IsNullOrEmpty(parameters[0].Name)))
在方法DynamicQueryable.OrderBy
更改行:
Expression.Parameter(source.ElementType, "")
为:
Expression.Parameter(source.ElementType, "it")
现在,query.OrderBy("Name")
将生成query.OrderBy(it => it.Name)
。
干杯!