Linq到NHibernate和Dynamic LINQ - 查询缓存无法正常工作

时间:2012-08-03 12:20:22

标签: linq nhibernate linq-to-nhibernate dynamic-linq

我对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私有实例)。

有什么想法吗?

克里斯

1 个答案:

答案 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库。

  1. 在方法ExpressionParser.ProcessParameters更改行:

    if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name))
    

    为:

    if (parameters.Length == 1 && (parameters[0].Name == "it" || String.IsNullOrEmpty(parameters[0].Name)))
    
  2. 在方法DynamicQueryable.OrderBy更改行:

    Expression.Parameter(source.ElementType, "")
    

    为:

    Expression.Parameter(source.ElementType, "it")
    
  3. 现在,query.OrderBy("Name")将生成query.OrderBy(it => it.Name)

    干杯!