NHibernate с Rhino Security - незаконно попытался связать прокси с двумя открытыми сессиями - PullRequest
4 голосов
/ 03 января 2012

Я использую Rhino Security в качестве уровня безопасности поверх NHibernate в приложении ASP.NET MVC 3. Когда я пытаюсь удалить защищенный объект, Rhino security запускает метод OnPreDelete, используемый для очистки соответствующих данных в базе данных. В этот момент я получаю Незаконно попытка связать прокси с двумя открытыми сессиями ошибка.

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)

Из моего прочтения по этой теме эта ошибка обычно вызвана плохим управлением сессиями, но из исходного кода видно, что Rhino Security использует существующую сессию (обратите внимание, что приведенный ниже вызов метода 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);

Мое управление сессиями также довольно простое, используя атрибут фильтра действий 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();
        }
    }
}

Может ли кто-нибудь дать руководство относительно того, почему возникает эта проблема?

Заранее спасибо

Ответы [ 2 ]

2 голосов
/ 10 января 2012

Я до сих пор не понимаю причину проблемы, но нашел обходной путь.Ранее мой метод удаления загружал прокси-сервер, а затем выполнял удаление

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();

Очевидно, что последний избегает создания проксии выполняет прямое удаление

1 голос
/ 09 января 2012

Имея подобную проблему, и даст ли это вам ответ, я не уверен, но из того, что я нашел в Интернете, все зависит от загрузки и обновления (или удаления в вашем случае) и объекта с неинициализированным свойством в течение того же сеанса. Таким образом, если загружаемый объект имеет свойство, установленное как LazyLoad (), которое никогда не вызывается, он не будет инициализирован, и поэтому сеанс, который использовался для получения объекта, будет доступен только для чтения и останется живым, ожидая заполнения заполненного отложенного свойства , Затем NHibernate попытается повторно использовать сеанс для обновления / удаления объекта, и будет выдано исключение.

Это мой взгляд на эту ссылку (относится к Java, но описывает проблему, с которой я сталкиваюсь в .Net) - http://blog.essaytagger.com/2011/11/avoiding-session-conflicts-on-save-due.html - хотя я не уверен, согласен ли я с исправлением к ней.

Надеюсь, это поможет каким-то образом.

...