给定如下的简单投影,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中不起作用
答案 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所建议的。