プロジェクトでは、特定のCastle AutomaticトランザクションとNHibernateIntegration機能であるいくつかのCastle機能を使用しています。
初期設定はメソッドごとのトランザクションでしたが、作業単位全体のロールバックに問題がありました。すべてが正常に機能していました。メソッドごとのこれらの小さなトランザクションのキャッスル構成は次のとおりです。
<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
}
}
}
これらの作業単位は、Web アプリケーションで要求ごとに 1 つ呼び出されます。しかし、その後、コレクションを2つの開いているセッションに関連付けようとする不正な試み、タイムアウトの期限切れなどの問題が発生し始めます。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。そして時にはデッドロック
最も頻繁に発生するエラーは次のとおりです。
「/」アプリケーションでサーバー エラーが発生しました。コレクションを 2 つの開いているセッションに関連付ける不正な試みです 説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。
例外の詳細: NHibernate.HibernateException: コレクションを 2 つの開いているセッションに関連付けようとする不正な試み
ソース エラー: 現在の Web 要求の実行中に未処理の例外が生成されました。例外の発生元と場所に関する情報は、以下の例外スタック トレースを使用して特定できます。
スタックトレース:
[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;
}
}
ここで 2 つのセッションがどのように使用されているかはわかりません。子トランザクションがすべて正常に機能する前は、同時実行性が大幅に低下しています。私の最初の考えでは、Castle AutoTX を使用したトランザクションのデフォルト値は、XML 構成ファイルでのみ宣言された XML のトランザクションの IsolationLevel.ReadCommited であり、一方、コード ファイルで宣言されたトランザクションは IsolationLevel.ReadUncommited です。子はこの動作を継承する必要があり、トランザクションに対して同じ Hibernate セッションも共有します。
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: Illegal attempts to associated a collection with two open sessions all in our unit of work, in the nested父との取引はこれらすべての問題です。IIS のプールを ASP.Net 4.0 Classic に変更しても、運が悪かった....
さまざまなことを試しましたが、何も機能していません。Castleバイナリのバージョンは次のとおりです。
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
似たような問題を抱えている人や、過去に似たような問題を抱えている人もいますか?