NHibernate 预选?
Posted
技术标签:
【中文标题】NHibernate 预选?【英文标题】:NHibernate PreSelect? 【发布时间】:2011-06-22 19:17:45 【问题描述】:我正在尝试使用 NHibernate 实现特权,而我想要做的是,每次有一个 Select 查询时,检查返回类型是什么,以及它是否是我想要的启用安全性的类型(例如发票)为 ICriteria 对象添加限制,限制仅检索某些记录(根据用户是否已读取全部或读取自己的权限)。
我设法为插入和更新实现了这些权限
NHibernater.Event.IPreUpdateEventListener
NHibernater.Event.IPreInsertEventListener
但不幸的是IPreLoadEventListener
是在查询数据库之后调用的,因此这是浪费,因为过滤将在计算机本地完成,而不是由数据库完成。
有谁知道 NHibernate 是否提供某种在执行查询之前调用的事件?
【问题讨论】:
【参考方案1】:如果您能够使用它,请查看Rhino.Security 它完全符合您的要求。即使你无法使用它,你也可以看到他对这个问题的实现。
【讨论】:
我正试图弄清楚如何使用它,但遇到了真正的困难 :( 现在我正在考虑使用过滤器实现 Frederik 的解决方案。 @LnDCobra,是的,关于它的文档并不多。【参考方案2】:您不能通过使用过滤器来实现这一点吗?
更多信息可以找到here
我在我的一个项目中将它与拦截器结合使用:
我有一些实体,每个用户都可以从中创建实例,但只有创建它们的用户才能看到/修改这些实例。其他用户看不到用户 X 创建的实例。
为此,我创建了一个接口IUserContextAware
。 “用户上下文感知”的实体实现了这个接口。
在构建会话工厂时,我创建了必要的过滤器:
var currentUserFilterParametersType = new Dictionary<string, NHibernate.Type.IType> (1);
currentUserFilterParametersType.Add (CurrentUserContextFilterParameter, NHibernateUtil.Guid);
cfg.AddFilterDefinition (new FilterDefinition (CurrentUserContextFilter,
"(:0 = UserId or UserId is null)".FormatString (CurrentUserContextFilterParameter),
currentUserFilterParametersType,
false));
完成后,我需要定义额外的过滤条件:
foreach( var mapping in cfg.ClassMappings )
if( typeof (IUserContextAware).IsAssignableFrom (mapping.MappedClass) )
// The filter should define the names of the columns that are used in the DB, rather then propertynames.
// Therefore, we need to have a look at the mapping information.
Property userProperty = mapping.GetProperty ("UserId");
foreach( Column c in userProperty.ColumnIterator )
string filterExpression = ":0 = 1";
// When the BelongsToUser field is not mandatory, NULL should be taken into consideration as well.
// (For instance: a PrestationGroup instance that is not User-bound (that can be used by any user), will have
// a NULL value in its BelongsToUser field).
if( c.IsNullable )
filterExpression = filterExpression + " or 1 is null";
mapping.AddFilter (CurrentUserContextFilter, "(" + filterExpression.FormatString (CurrentUserContextFilterParameter, c.Name) + ")");
break;
现在,每当我实例化 ISession
时,我都会指定应该使用某个拦截器:
这个拦截器确保过滤器中的参数被填充:
internal class ContextAwareInterceptor : EmptyInterceptor
public override void SetSession( ISession session )
if( AppInstance.Current == null )
return;
// When a User is logged on, the CurrentUserContextFilter should be enabled.
if( AppInstance.Current.CurrentUser != null )
session.EnableFilter (AppInstance.CurrentUserContextFilter)
.SetParameter (AppInstance.CurrentUserContextFilterParameter,
AppInstance.Current.CurrentUser.Id);
【讨论】:
这听起来很完美 :) 谢谢!这篇文章有助于更好地理解过滤器:P nhforge.org/doc/nh/en/index.html#filters 实际上,我刚刚意识到这行不通,因为我有一个权限表,因此过滤器会一直针对所有不同的实体(甚至随着时间的推移同一个实体)而变化跨度>以上是关于NHibernate 预选?的主要内容,如果未能解决你的问题,请参考以下文章
Nhibernate学习教程-- 第一个NHibernate程序
NHibernate 2 + NHibernate.JetDriver + MS Access:如何访问表的“附件”字段