2012-08-02 8 views
5

MVC 4プロジェクトでNServiceBus(3.2.2)、RavenDB(1.2.2017-Unstable)、Windsor(3.0.0.4001)を使用しています。NserviceBusのWindsorでRavenDbセッションを管理する

私は3種類のメッセージを処理IHandleMessagesクラスを持って、そしてそれがIDocumentSessionが必要で、そのためのようなプロパティを定義しています。私はNServiceBus' website

からRavenDbUnitOfWorkの実装をコピーした

public IDocumentSession DocumentSession { get; set; } 

私は次のように私のウィンザーコンテナにIDocumentStore、IDocumentSessionとIManageUnitsOfWorkを登録しました:

container.Register(
      Component 
       .For<IManageUnitsOfWork>() 
       .ImplementedBy<RavenUnitOfWork>() 
       .LifestyleTransient() 
      ); 
container.Register(
      Component 
       .For<IDocumentStore>() 
       .UsingFactoryMethod(k => DocumentStoreHolder.DocumentStore) 
       .LifestyleSingleton(), 
      Component 
       .For<IDocumentSession>() 
       .UsingFactoryMethod(k => k.Resolve<IDocumentStore>().OpenSession()) 
       .LifestyleTransient() 
      ); 

NServiceBusは私のコンテナを使用するように設定されています。私はUnitOfWorkのとメッセージハンドラはDocumentSessionの異なるインスタンスを受け取る問題が発生してい

Configure.With() 
     .CastleWindsorBuilder(container); 

。これは、SaveChanges()が別のDocumentSessionで呼び出されるため、メッセージハンドラのセッションに格納されているオブジェクトは保存されないことを意味します。

一時的なライフスタイルを削除すると、メッセージハンドラがDocumentSessionの同じインスタンスを取得し続けるため、RavenDbからオブジェクトを更新するときに並行性/競合が発生するさまざまな種類の問題が発生します。オブジェクト。

更新:

示唆したように、私はこのように、スコープのライフスタイルに、ウィンザーにIDocumentSessionの登録を変更しようとしました:とき、コンテナの試行

Component 
    .For<IDocumentSession>() 
    .UsingFactoryMethod(k => k.Resolve<IDocumentStore>().OpenSession()) 
    .LifestyleScope() 

これは、例外が発生スコープが見つからないと言ってMVCコントローラを解決し、BeginScope()を呼び出すのを忘れたかどうかを尋ねる。

+0

あなたはDocumentStoreHolderに定義を追加することができます。nservicebusへ? –

答えて

4

トランジエントまたはシングルトンではなく、メッセージごとのスコープが必要です。

+0

+1、LifecyleType.Scopedは必要なものですhttps://github.com/NServiceBus/NServiceBus/blob/master/src/impl/ObjectBuilder/ObjectBuilder.CastleWindsor/WindsorObjectBuilder.cs#L175 –

+0

また、そうではありませんRavenUnitOfWorkはDocumentSessionインスタンスの管理に使用されていますか? – SaguiItay

+1

UoWは.SaveChangesを呼び出すためのものです。作成と処分はコンテナによって行われます。そのため、スコープを使用してメッセージごとに新しいセッションを取得する必要があります –

0

あなたのmvcコントローラがIDocumentStoreに直接依存していると仮定しています。 Webからの各リクエストの前にcontainer.BeginScope()を呼び出す必要があります。これをアクションフィルタ属性http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute.aspxとして、コントローラ自体のAOPアスペクトとしてhttp://cangencer.wordpress.com/2011/06/02/asp-net-mvc-3-aspect-oriented-programming-with-castle-interceptors/のいずれかで行うことができます。

0

同じコンテナ内でIDocumentSessionを共有するときに、asp.net mvcのWebサイトでnservicebusを使用する際には、さまざまなライフスタイルが必要です。

ASP.NET MVCの場合、PerWebRequestライフスタイルが必要で、NServiceBusにはScopedライフスタイルが必要です。

は、私は城のcontribプロジェクトにハイブリッドライフスタイルのコードを使用していたことを実行します。 https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles/tree/master/Castle.Windsor.Lifestyles

ASP.NETコンテキストから呼び出して、それがWebRequestScopeAccessorを使用しています。 NServicebusの場合、LifetimeScopeAccessorが必要です。これはcontribのプロジェクトではありませんが、追加するのは簡単です:

public class HybridPerWebRequestLifetimeScopeScopeAccessor : HybridPerWebRequestScopeAccessor 
{ 
    public HybridPerWebRequestLifetimeScopeScopeAccessor() 
     : base(new LifetimeScopeAccessor()) 
    { 
    } 
} 

そして、あなたの登録コードに次のようなものが必要です。

container.Register(Component.For<IDocumentSession>().LifestyleScoped<HybridPerWebRequestLifetimeScopeScopeAccessor>().UsingFactoryMethod(() => RavenDbManager.DocumentStore.OpenSession())); 

をそして、ここで私は切り替え前に使用Rhinoのサービスバスのための実装です

https://gist.github.com/4655544