Linq Projection在NHibernate 3.2中被错误地缓存

时间:2012-01-05 22:59:41

标签: c# .net linq nhibernate

给定如下的简单投影,NHibernate将缓存查询计划,而不是在查询相同时更新变量的值:

    int argValue = 1;
    var result1 = database.Users.Select(x => new {x.Name, BadArg = argValue}).First();

    argValue = 2;
    var result2 = database.Users.Select(x => new {x.Name, BadArg = argValue}).First();

预期

result1值为Name =“Bob”,BadArg = 1

result2值为Name =“Bob”,BadArg = 2

实际

result1值为Name =“Bob”,BadArg = 1

result2值为Name =“Bob”且 BadArg = 1

显然,如果你不期待它,这可能会导致许多疯狂的行为。我在NHibernate的bug跟踪中看到了类似于couple bug reports的{{3}},但自去年五月以来就没有采取任何行动。所以要么没有人非常使用Linq来Nhibernate,要么有一些我不知道的解决方法。

在深入了解NHibernate源码之前,是否有办法禁用查询计划缓存以防止此行为或其他一些变通方法,或者是否有人从上述链接应用了该补丁?

注意

这个例子是为了让这个问题变得简单,实际上我有一个复杂的投影,我想保留为IQueryable,过早地转换为IEnumerable将不起作用。

更新 在Nhibernate 3.2.1的github master中不起作用

2 个答案:

答案 0 :(得分:0)

如果您想完全避免缓存,请尝试将代码更改为:

int argValue = 1;
var result1 = database.Users.AsEnumerable().Select(x => new {x.Name, BadArg = argValue}).First();

argValue = 2;
var result2 = database.Users.AsEnumerable().Select(x => new {x.Name, BadArg = argValue}).First();

不会使用NHLinq Select方法,您将最终使用System.Linq Select方法 - 有效防止NHibernate缓存投影。当然,缺点是您将在内存中进行投影,因此您最终会从用户表中选择所有字段,而不仅仅是您想要的字段。

答案 1 :(得分:0)

以下是禁用第一级缓存的方法: http://darioquintana.com.ar/blogging/2007/10/08/statelesssession-nhibernate-without-first-level-cache/

我认为您不能禁用二级缓存,但我认为您不必解决此问题。

(基本上你需要为每个查询创建和销毁会话。)

如果您发现问题仍然存在,那么您将不得不做Rytmis所建议的。