5

MVC 4 プロジェクトで NServiceBus (3.2.2)、RavenDB (1.2.2017-Unstable)、Windsor (3.0.0.4001) を使用しています。

3 つの異なるメッセージを処理する IHandleMessages クラスがあり、IDocumentSession が必要なため、次のようなプロパティを定義します。

public IDocumentSession DocumentSession { get; set; }

NServiceBus のWeb サイトから RavenDbUnitOfWork 実装をコピーしました

次のように、Windsor コンテナーに 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 は私のコンテナーを使用するように構成されています。

Configure.With()
         .CastleWindsorBuilder(container);

UnitOfWork とメッセージ ハンドラが DocumentSession の異なるインスタンスを受け取るという問題が発生しています。これは、SaveChanges() が別の DocumentSession で呼び出されるため、メッセージ ハンドラーのセッションに格納されたオブジェクトが保存されないことを意味します。

一時的なライフスタイルを削除すると、さまざまな種類の問題が発生し、RavenDb からオブジェクトを更新するときに同時実行/競合が発生します。これは、(おそらく) メッセージ ハンドラーが、更新されたオブジェクトのキャッシュ バージョンを保持する DocumentSession の同じインスタンスを取得し続けるためです。

アップデート:

示唆されているように、Windsor での IDocumentSession の登録を、次のように Scope ライフスタイルに変更してみました。

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

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

4

3 に答える 3

4

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

于 2012-08-02T18:44:56.237 に答える
0

問題は、同じコンテナーでIDocumentSessionを共有するときに、asp.net mvc Webサイトでnservicebusを使用する場合、異なるライフスタイルが必要になることです。

ASP.NET MVCの場合は、PerWebRequestライフスタイルが必要であり、NServiceBusの場合は、スコープ付きライフスタイルが必要です。

そのために、私は城の貢献プロジェクトでハイブリッドライフスタイルコードを使用しました: 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()));

そして、nservicebusに切り替える前に使用したRhinoServiceBusの実装は次のとおりです。

https://gist.github.com/4655544

于 2013-01-28T13:36:49.957 に答える
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/ .

于 2012-08-15T06:15:27.903 に答える