3

我对 NHibernate 的二级缓存有疑问。当我使用查询时:

        var items1 = Session.Query<Row>()
            .Cacheable();
            .Fetch(x => x.Field)
            .OrderBy(x => x.Field.Value)
            .ToList();

一切都很好 - 查询被缓存。但是当我想使用 Dynamic Linq (链接)时:

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

有任何想法吗?

克里斯

4

1 回答 1

2

好的,我知道是什么原因了。

动态 Linq 不在 Linq 表达式中使用参数名称。例如,如果我想使用 lambda statemant 进行排序,我会写:

query.OrderBy(item => item.Name)

上面我们看到了一个itemlambda 参数名称。

当我使用动态 linq 时:

query.OrderBy("Name")

在查询结果中,OrderBy 方法中的 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")
    

现在,query.OrderBy("Name")将产生query.OrderBy(it => it.Name).

干杯!

于 2012-08-14T14:00:18.607 回答