多用户环境中的NHibernate QueryCache

时间:2011-09-15 15:56:02

标签: fluent-nhibernate nhibernate-criteria nhibernate-caches

对于我们的Web应用程序(ASP.NET),我们使用Fluent NHibernate(2.1.2)进行二级缓存,不仅用于实体,还用于查询(使用条件API生成查询)。我们使用Session-Per-Request模式和一个SessionFactory应用程序范围,因此缓存服务于所有Nhibernate-Sessions。


问题:

我们必须在遗留数据库(Oracle)中的数据对象上处理每个用户的不同“Access-Rigths” - 也就是说,视图限制每个用户权限的返回数据。 因此存在这样的情况,例如,我们的条件使用相同的查询查询相同的视图,但返回不同的结果集,具体取决于用户权限。

现在,为了获得性能,缓存了上述查询。但这给我们带来了一个问题,即当查询首先从用户A的操作中触发时,它会缓存生成的ID,即用户A具有访问权限的ID。不久之后,从用户B的操作触发相同的查询,然后Nhibernate从第一次调用(来自用户A)中选择缓存的ID,并尝试获取用户B没有访问权限的相应实体(或者可能不适用于所有人)。我们正在检查事件监听器的权限,因此我们的应用程序会在上述情况下抛出访问权限异常。


思想:

不缓存查询可能是一个选项。但是在我们的应用程序中,性能是一个很明显的问题,因此用户可以更好地使用缓存查询。

我们甚至考虑过每个用户的SessionFactory,每个用户都有一个缓存。但这显然对资源有影响,有点过分,老实说不是一种选择,因为 有些实体,必须由多个用户(想到用户组)进行访问和操作,在“单个缓存”中创建陈旧数据的问题,等等。所以这是不行的。

什么是有效的解决方案?对于这种情况,是否有类似“最佳实践”的内容?


昨天我被困在这里,没有出路,我睡过了,今天我想出了某种“黑客”。

当NHibernate通过查询文本和参数(“子句”)缓存查询时,我想到了一种方法,在查询的签名中“走私”用户依赖的东西,所以它会 缓存每个用户的每个查询,但不会改变查询本身(关于查询的结果)。

所以“创造力”引导我去做这个(示例代码):

string userName = GetCurrentUser();
ICriteria criteria = session.CreateCriteria(typeof (EntityType))
            .SetCacheable(true)
            .SetCacheMode(CacheMode.Normal)
            .Add(Expression.Eq("PropertyA", 1))
            .Add(Expression.IsNotNull("PropertyB"))
            .Add(Expression.Sql(string.Format("'{0}' = '{0}'", userName)));
return criteria.List();

这一行:

  

.Add(Expression.Sql(string.Format(“{0} = {0}”,userName)))

产生一个where子句,它总是计算为true,但是从Nhibernate的角度“更改”查询,因此它按单独的“userName”进行缓存。

我知道,这有点难看,我对此并不满意。 有人知道任何替代方法吗?

提前感谢。

0 个答案:

没有答案