NHibernate with Rhino Security - Unlawfully attempted to associate proxies with two open sessions

I use Rhino Security as my security level on top of NHibernate in an ASP.NET MVC 3 application. When I try to delete a protected object, the Rhino system disables the OnPreDelete method used to clear the corresponding data in the database. At this point, I get an Unlawful attempt to associate a proxy with two open sessions .

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) 

From my reading on the topic, this error is usually caused by improper session management, but from the source code it seems that Rhino Security is using an existing session (note that the Delete method method below is a violation method):

 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 management is also quite simple using the MVC action filter attribute to open and commit transactions as follows:

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

Can someone give guidance as to why this problem occurs?

Thank you in advance

+4
source share
2 answers

I still do not understand the root cause of the problem, but found a workaround. Previously, my uninstall method downloaded proxies and then did the uninstall

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

Replacing the above code, follow these steps:

  var queryString = string.Format("delete {0} where id = :id", typeof(T)); Session.CreateQuery(queryString) .SetParameter("id", id) .ExecuteUpdate(); 

Obviously, the latter avoids creating a proxy server and does a direct delete

+2
source

Having a similar problem, and whether this will provide an answer for you, I am not sure, but from what I found on the Internet, this is before downloading and updating (or deleting in your case) and an object with an uninitialized property during the same session. Therefore, if the object being loaded has a property set as LazyLoad () that is never called, it will not be initialized, and therefore the session that was used to get the object will be read-only and will remain alive, waiting for the lazy loaded properties, then NHibernate will try to reuse the session to update / delete the object, and an exception will be thrown.

What I take to this link (applies to Java, but describes the problem that I see in .Net) - http://blog.essaytagger.com/2011/11/avoiding-session-conflicts-on-save-due.html - although I'm not sure if I agree with this correction.

Hope this helps in some way.

+1
source

Source: https://habr.com/ru/post/1389013/


All Articles