Linq到NHibernate和动态Linq-查询缓存不工作
我对NHibernate的二级缓存有问题。使用查询时:Linq到NHibernate和动态Linq-查询缓存不工作,linq,nhibernate,linq-to-nhibernate,dynamic-linq,Linq,Nhibernate,Linq To Nhibernate,Dynamic Linq,我对NHibernate的二级缓存有问题。使用查询时: var items1 = Session.Query<Row>() .Cacheable(); .Fetch(x => x.Field) .OrderBy(x => x.Field.Value) .ToList(); 缓存再次起作用。因此,问题在于同时使用Fetch和动态linq OrderBy方法 编辑
var items1 = Session.Query<Row>()
.Cacheable();
.Fetch(x => x.Field)
.OrderBy(x => x.Field.Value)
.ToList();
缓存再次起作用。因此,问题在于同时使用Fetch和动态linq OrderBy方法
编辑:
当我尝试调试NH代码(QueryKey类)时,调试器告诉我这两个查询没有相同的ResultTransformer(以及更深层的:listTransformation私有实例)
有什么想法吗
克里斯:好的,我知道原因是什么 动态Linq在Linq表达式中不使用参数名称。例如,如果我想使用lambda statemant进行排序,我会写:
query.OrderBy(item => item.Name)
上面我们看到一个项
lambda参数名
当我使用动态linq时:
query.OrderBy("Name")
在可查询的结果中,OrderBy mehod中的lambda参数没有名称(如上面写的item
)。我们可以这样说明结果:
query.OrderBy( => .Name)
现在,当NHibernate解码这个可查询表达式时,发现有一个表达式参数没有名称,NH使用GUID类给它一个随机名称。因此,使用动态linq的每个排序都会生成一个具有可变lambda参数的可查询表达式。这就是NHibernate认为:query.OrderBy(“Name”)
和query.OrderBy(“Name”)
不一样的原因,它们每次都会从头生成另一个lamda参数
解决方案
如果要修复它,必须修改动态Linq库
ExpressionParser.ProcessParameters
中更改行:
if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name))
Expression.Parameter(source.ElementType, "")
致:
DynamicQueryable.OrderBy
更改行中:
if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name))
Expression.Parameter(source.ElementType, "")
致:
query.OrderBy(“Name”)
将生成query.OrderBy(it=>it.Name)
干杯 您使用的是NH的哪个版本?可能在通过NH识别查询时存在问题。我不知道NH如何存储用于比较和从缓存加载的查询标识符(整个SQL?)。但当我比较第一个和第二个示例中的ExpressionTree时(在调用ToList之前),它们是相同的。两个查询发出的查询字符串(sql)是否不同?(即,包括提取?)。NHibernate使用
QueryKey
对象作为其查询缓存,该对象包含查询字符串、其参数和筛选器值。发出的查询字符串是相同的(由log4net检查)。当我尝试调试NH代码(QueryKey类)时,调试器告诉我这两个查询没有相同的结果转换器(还有更深层的:一个listTransformation实例)。对于任何在这方面遇到障碍的人来说,NHibernate 3.3.2解决了这个问题。
Expression.Parameter(source.ElementType, "")
Expression.Parameter(source.ElementType, "it")