带有 Rhino 安全性的 NHibernate - 非法尝试将代理与两个打开的 session 相关联

标签 nhibernate rhino-security

我在 ASP.NET MVC 3 应用程序中使用 Rhino Security 作为我在 NHibernate 之上的安全层。当我尝试删除安全实体时,Rhino 安全性会触发 OnPreDelete 方法,用于清理数据库中的相应数据。此时我收到了 非法尝试将代理与两个打开的 session 相关联 错误。

2012-01-02 21:47:52,176 [9] ERROR NHibernate.Event.Default.AbstractFlushingEventListener [(null)] - Could not synchronize database state with session
NHibernate.LazyInitializationException: Initializing[Rhino.Security.Model.EntityType#8007cc24-9cdd-447c-a9cd-9fcc015fa95c]-Illegally attempted to associate a proxy with two open Sessions
   at NHibernate.Proxy.AbstractLazyInitializer.set_Session(ISessionImplementor value)
   at NHibernate.Engine.StatefulPersistenceContext.ReassociateProxy(ILazyInitializer li, INHibernateProxy proxy)
   at NHibernate.Engine.StatefulPersistenceContext.ReassociateIfUninitializedProxy(Object value)
   at NHibernate.Event.Default.ProxyVisitor.ProcessEntity(Object value, EntityType entityType)
   at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Object value, IType type)
   at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Int32 i, Object[] values, IType[] types)
   at NHibernate.Event.Default.AbstractVisitor.ProcessEntityPropertyValues(Object[] values, IType[] types)
   at NHibernate.Event.Default.AbstractVisitor.Process(Object obj, IEntityPersister persister)
   at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event, ISet transientEntities)
   at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event)
   at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event)
   at NHibernate.Impl.SessionImpl.Delete(Object obj)
   at Rhino.Security.DeleteEntityEventListener.OnPreDelete(PreDeleteEvent deleteEvent) in C:\Users\jirwin\Downloads\rhino\rhino-security\Rhino.Security\DeleteEntityEventListener.cs:line 43
   at NHibernate.Action.EntityDeleteAction.PreDelete()
   at NHibernate.Action.EntityDeleteAction.Execute()
   at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
   at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
   at NHibernate.Engine.ActionQueue.ExecuteActions()
   at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)

从我对这个主题的阅读来看,这个错误通常是由糟糕的 session 管理引起的,但从源代码看来,Rhino Security 正在使用现有的 session (注意,下面的 Delete 方法调用是有问题的方法):
ISession childSession = deleteEvent.Session.GetSession(EntityMode.Poco);    
// because default flush mode is auto, a read after a scheduled delete will invoke
// the auto-flush behaviour, causing a constraint violation exception in the 
// underlying database, because there still are EntityGroup entities that need
// the deleted EntityReference/SecurityKey.
childSession.FlushMode = FlushMode.Commit;    
childSession.Delete(entityReference);

我的 session 管理也非常简单,使用 MVC 操作过滤器属性来打开和提交事务,如下所示:
public class NHibernateActionFilter : ActionFilterAttribute
{
    private static readonly ISessionFactory sessionFactory = BuildSessionFactory();

    private static ISessionFactory BuildSessionFactory()
    {
        return new Configuration()
            .Configure()
            .BuildSessionFactory();
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var sessionController = filterContext.Controller as SessionController;

        if (sessionController == null)
            return;

        sessionController.Session = sessionFactory.OpenSession();
        sessionController.Session.BeginTransaction();
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var sessionController = filterContext.Controller as SessionController;

        if (sessionController == null)
            return;

        using (var session = sessionController.Session)
        {
            if (session == null)
                return;

            if (!session.Transaction.IsActive) 
                return;

            if (filterContext.Exception != null)
                session.Transaction.Rollback();
            else
                session.Transaction.Commit();
        }
    }
}

任何人都可以提供有关为什么会出现此问题的指导吗?

提前致谢

最佳答案

我仍然不明白问题的根本原因,但找到了解决方法。以前我的删除方法加载了一个代理,然后执行删除

var entity = session.Load<T>(21415);
session.Delete(entity);

用以下代码替换上面的代码解决了这个问题:
 var queryString = string.Format("delete {0} where id = :id", typeof(T));
            Session.CreateQuery(queryString)
                   .SetParameter("id", id)
                   .ExecuteUpdate();

显然后者避免了创建代理并执行直接删除

关于带有 Rhino 安全性的 NHibernate - 非法尝试将代理与两个打开的 session 相关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8707585/

相关文章:

c# - 映射实体无法完成,因为它找不到属性

java - 如何在 Rhino JavaScript 引擎中配置沙盒安全性

c# - 处理由无法访问的数据库引起的 NHibernate 延迟加载异常

c# - NHibernate:单个 session 中的多个事务

c# - 为什么调用 Session.Clear() 会导致此测试失败?

c# - 如何实现 C# Rhino 安全

nhibernate - NHibernate Profiler 的初始启动方式

asp.net-mvc-2 - 查找要在 ASP.NET MVC 项目上使用的授权框架

Nhibernate 和 SetCacheable 与二级缓存