2012-09-06 3 views
1

우리는 Castle 자동 트랜잭션과 NHibernateIntegration 기능을 위해 성 기능을 프로젝트에서 사용하고 있습니다.Castle.Facilities.AutoTx 오류와의 트랜잭션 문제 "두 개의 열린 세션으로 콜렉션을 연결하려고 시도가 잘못되었습니다."

초기 설정은 메소드 당 트랜잭션 이었지만 전체 작업 단위를 롤백하는 데 문제가있었습니다. 모두 잘 작동했다.

<component id="SessionModule" 
      service="BCS.Modules.ISessionModule, BCS.Modules" 
      type="BCS.Modules.SessionModule, BCS.Impl" 
      isTransactional="true">  
    <transaction> 
     <method name="GetCurrentDate" /> 
     <method name="GetCurrentDateAndTime" /> 
    </transaction> 
    </component> 

그런 다음 우리는 전체 요청에서 롤백 작업에 문제가 시작, 그래서 우리는 예에 의해 아버지의 트랜잭션 그룹에 비즈니스 트랜잭션 당 모든 단일 트랜잭션을 결정 : 방법 당이 작은 트랜잭션에 대한 우리의 성 구성은 다음과 같습니다

namespace BCS.BusinessRules { 
    [Transactional] 
    public class TransactionModule : ITransactionModule { 

     [Transaction(TransactionMode.Requires, IsolationMode.ReadUncommitted, Distributed = false)] 
     public Dictionary<String, double> CalculateGoalSetting(Member member, WorkflowContext contextSetting) { 
     // Calling a lot of child transactional methods for this unit of work 
     } 

     [Transaction(TransactionMode.Requires, IsolationMode.ReadUncommitted, Distributed = false)] 
     public MembershipOperationResult SelfEnrollment(Member member) { 
      // Same here, Another unit of work  
     } 

    } 

} 

이러한 작업 단위 (unit)는 웹 애플리케이션에서 요청 당 하나씩 호출됩니다. 그러나 그 후에는 과 같은 문제가 발생하기 시작합니다. 두 개의 열린 세션이있는 컬렉션을 연결하려고 시도했습니다., 제한 시간이 만료되었습니다. 작업이 완료되기 전에 시간 초과 기간이 경과되었거나 서버가 응답하지 않습니다.와 몇 번 죽은 잠금

가장 흔한 오류입니다 : '/'응용 프로그램에

서버 오류가 발생했습니다. 두 개의 열린 세션을 가진 컬렉션을 연결할 때 잘못된 시도가 발생했습니다. 설명 : 현재 웹 요청을 실행하는 동안 처리되지 않은 예외가 발생했습니다. 오류 및 코드에서 시작된 위치에 대한 자세한 정보는 스택 추적을 검토하십시오.

예외 정보 : NHibernate.HibernateException : 처리되지 않은 예외가 현재 웹 요청을 실행하는 동안 생성 된 두 개의 열린 세션

소스 오류와 함께 컬렉션을 연결하는 불법 시도. 예외의 출처와 위치에 관한 정보는 아래의 예외 스택 추적을 사용하여 식별 할 수 있습니다.

스택 추적 :

[HibernateException: Illegal attempt to associate a collection with two open sessions] 
    NHibernate.Collection.AbstractPersistentCollection.SetCurrentSession(ISessionImplementor session) +242 
    NHibernate.Event.Default.OnUpdateVisitor.ProcessCollection(Object collection, CollectionType type) +177 
    NHibernate.Event.Default.AbstractVisitor.ProcessEntityPropertyValues(Object[] values, IType[] types) +83 
    NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformUpdate(SaveOrUpdateEvent event, Object entity, IEntityPersister persister) +632 
    NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event) +101 
    NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event) +365 
    NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event) +394 
    NHibernate.Impl.SessionImpl.SaveOrUpdate(String entityName, Object obj) +392 
    NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything) +578 
    NHibernate.Event.Default.AbstractFlushingEventListener.CascadeOnFlush(IEventSource session, IEntityPersister persister, Object key, Object anything) +157 
    NHibernate.Event.Default.AbstractFlushingEventListener.PrepareEntityFlushes(IEventSource session) +364 
    NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) +225 
    NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) +83 
    NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) +474 
    NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) +782 
    NHibernate.Impl.CriteriaImpl.List(IList results) +63 
    NHibernate.Impl.CriteriaImpl.UniqueResult() +69 
    BCS.Modules.Behavior.BehaviorElementDataAccess.GetByName(String name) in c:\Projects\dps\bcs\branches\bcs31\BCS.Impl\Modules\Behavior\BehaviorElementDataAccess.cs:41 
    BCS.Modules.Behavior.BehaviorManagerModule.FindBehaviorElementByName(String behaviorName) in c:\Projects\dps\bcs\branches\bcs31\BCS.Impl\Modules\Behavior\BehaviorManagerModule.cs:191 
    Castle.Proxies.Invocations.IBehaviorManagerModule_FindBehaviorElementByName.InvokeMethodOnTarget() +147 
    Castle.DynamicProxy.AbstractInvocation.Proceed() in e:\OSS.Code\Castle.Core\src\Castle.Core\DynamicProxy\AbstractInvocation.cs:144 
    Castle.Facilities.AutoTx.TransactionInterceptor.Intercept(IInvocation invocation) in c:\dev\dotnet\castle\main\Castle.Facilities.AutomaticTransactionManagement\src\Castle.Facilities.AutoTx\TransactionInterceptor.cs:92 
    Castle.DynamicProxy.AbstractInvocation.Proceed() in e:\OSS.Code\Castle.Core\src\Castle.Core\DynamicProxy\AbstractInvocation.cs:166 
    Castle.Proxies.IBehaviorManagerModuleProxy.FindBehaviorElementByName(String behaviorName) +356 
    KAO.Behavior.CommonBehaviorCalculations.SaveGoalActivityMinutes(Member member, JulianDate startingDate, JulianDate endingDate, JulianDate currentDate) in c:\svn\qupio21\KAO\Behavior\CommonBehaviorCalculations.cs:148 
    KAO.BusinessRules.TransactionModule.CalculateGoalSetting(Member member, WorkflowContext contextSetting) in c:\svn\qupio21\KAO.BusinessRules\TransactionModule.cs:111 
    Castle.Proxies.Invocations.ITransactionModule_CalculateGoalSetting.InvokeMethodOnTarget() +155 
    Castle.DynamicProxy.AbstractInvocation.Proceed() in e:\OSS.Code\Castle.Core\src\Castle.Core\DynamicProxy\AbstractInvocation.cs:144 
    Castle.Facilities.AutoTx.TransactionInterceptor.Intercept(IInvocation invocation) in c:\dev\dotnet\castle\main\Castle.Facilities.AutomaticTransactionManagement\src\Castle.Facilities.AutoTx\TransactionInterceptor.cs:169 
    Castle.DynamicProxy.AbstractInvocation.Proceed() in e:\OSS.Code\Castle.Core\src\Castle.Core\DynamicProxy\AbstractInvocation.cs:166 
    Castle.Proxies.ITransactionModuleProxy.CalculateGoalSetting(Member member, WorkflowContext context) +183 
    BCS.Web.App.Landing.Tunneling.Goals.cmdCalculate_Click(Object sender, EventArgs e) in c:\svn\qupio21\BCS.Web.App\Landing\Tunneling\Goals.aspx.cs:104 
    System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +155 
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3707 


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272 

우리의 데이터 액세스 계층은 현재 오픈 세션의 NHibernate에 통합 기능을 사용하고 있습니다 :

public class BehaviorElementDataAccess : DataAccessBase<BehaviorElement, Int64>, IBehaviorElementDataAccess { 

     public BehaviorElementDataAccess(ISessionManager sessionManager) : base(sessionManager) { } 


     public T GetById<T>(long id) where T : BehaviorElement { 
     T ret; 
     using (ISession session = SessionManager.OpenSession()) { 
      ret = session.Load<T>(id); 
      session.Evict(ret); 
     } 
     return ret; 
     } 
} 

우리는 두 개의 세션이 여기에 사용하는 방법을 모른다, 하위 트랜잭션이 모두 정상적으로 작동하기 전에는 이제 동시성이 크게 감소했습니다. 캐슬 AutoTX를 사용하는 트랜잭션의 기본값은 XML 구성 파일에서만 선언 된 XML의 경우 IsolationLevel.ReadCommited이고, 반면에 코드 파일에 선언 된 트랜잭션 인 경우 IsolationLevel.ReadUncommited입니다. 따라서이 동작을 상속받은 자식 객체는 트랜잭션에 대해 동일한 최대 절전 모드 세션을 공유합니다.

Nhibernate 수준에서 데이터베이스의 격리 수준이이 영향을 받습니까? 우리는> 우리 시설의 데이터베이스에 대해이 설정을 가지고 :

<?xml version="1.0" encoding="utf-8" ?> 
<castle> 
     <!-- Facilities --> 
     <facilities> 
      <facility id="atm" type="Castle.Facilities.AutoTx.TransactionFacility, Castle.Facilities.AutoTx"> 
      </facility> 
      <facility id="nhibernate" type="Castle.Facilities.NHibernateIntegration.NHibernateFacility, Castle.Facilities.NHibernateIntegration"> 
      <factory id="nhibernate.factory" alias="nh.facility.default"> 
       <settings> 
        <item key="connection.provider">NHibernate.Connection.DriverConnectionProvider</item> 
        <item key="connection.driver_class">NHibernate.Driver.SqlClientDriver</item> 
        <item key="connection.connection_string_name">SQLServerConnection</item> 
        <item key="connection.isolation">ReadCommitted</item> 
        <item key="dialect">NHibernate.Dialect.MsSql2008Dialect</item> 
        <item key="adonet.batch_size">0</item> 
        <item key="use_outer_join">true</item> 
        <item key="query.substitutions">true 1, false 0, yes 'Y', no 'N'</item> 
        <item key="show_sql">true</item> 
        <item key="command_timeout">600</item> 
        <item key="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</item> 
        <item key="cache.use_minimal_puts">true</item> 
       </settings> 
       <assemblies> 
        <assembly>BCS.Impl</assembly> 
       </assemblies> 
       <listeners> 
        <listener type="BCS.NHibernate.Types.ActivitySaveUpdateListener, BCS.Impl" event="Save"/> 
        <listener type="BCS.NHibernate.Types.ActivitySaveUpdateListener, BCS.Impl" event="Update"/> 
        <listener type="BCS.NHibernate.Types.ActivitySaveUpdateListener, BCS.Impl" event="SaveUpdate"/> 
        <listener type="BCS.NHibernate.Types.ActivityDeleteListener, BCS.Impl" event="Delete"/> 
       </listeners> 

      </factory> 
      </facility> 
     </facilities> 

     <include uri="file://modules.cfg.xml" /> 

    </castle> 

내가 작업 롤백의 단위가 완벽하게 작동 언급해야하지만 동시에 일부 사용자가 NHibernate에있어.HibernateException : 우리의 작업 단위에 두 개의 열린 세션 모두를 가진 콜렉션을 연관시키려는 잘못된 시도, 다른 한편으로는 이러한 모든 문제를 아버지와 중첩 된 트랜잭션. 우리는 IIS 풀을 ASP.Net 4.0 Classic으로 변경합니다.

우리는 다른 것들을 시도했지만 아무런 효과가 없습니다. 우리의 성 바이너리 버전은 다음과 같습니다

Castle.Facilities.AutoTx 2.5.1.0 
Castle.Facilities.NHibernateIntegration 1.1.0.0 
Castle.Services.Transaction 2.5.0.0 
Castle.Windsor 2.5.1.0 
NHibernate.ByteCode.Castle 3.1.0.4000 
NHibernate 3.1.0.4000 
ASP.Net 4.0 

일부는 비슷한 문제가 있거나 과거에 이와 유사한있어?

답변

0

BehaviorElementDataAccess.GetById 메소드에서 사용자가로드 한 엔티티가 제거되고 세션에서 제거됩니다. 그러나 관련 엔터티 (특히이 인스턴스의 컬렉션)에 대해서는 아무 것도하지 않습니다.

NHibernate는 엔티티를로드하는 중입니다. 그러면 NHibernate는 연관된 콜렉션에 대한 프록시를 생성하고 이러한 프록시는 세션에 대한 참조를 유지하고로드 된 엔티티를 제거 할 때 프록시는 여전히이 참조를 가지며, 엔티티가 퇴출 되었기 때문에 동일한 세션에서 나중에 다시 저장하려고하면 NHibernate는 엔티티를 세션에 다시 연결하려고 시도하지만 그렇게하면 이미 참조가있는 콜렉션 프록시를 다시 연결하려고 시도합니다 세션에 연결하면 오류가 발생합니다.

GetById 메서드에서 엔티티를 왜 추방하는지 확신 할 수 없습니다. NHibernate에서 제공하는 많은 기능을 우회하고 있습니다.

+0

트랜잭션에서 세션의 객체를 제거하면 문제가 발생합니다. 감사합니다 =) – jpeep

관련 문제