0

SO で多くの Q/A を見てきましたが、EF を使用したマルチスレッド化は難しい可能性があると言っています。

私が得たシナリオは、Web API がデータベース内のジョブをキューに入れるというものです。Windows サービス (現時点では実際にはコンソール アプリ) がこれらのジョブを取得し、複数のスレッドで実行して、結果をデータベースに保存します。

現時点ではリポジトリ パターンを使用しており、最初はメイン スレッドのみを使用してデータベースを更新しようとしました。これは、メイン スレッドがデータベースを更新できるよりも (はるかに) 速く作業が行われるため、特に結果が多数 (数万) ある場合には機能しません。

次のアプローチは、スレッドごとのコンテキストに移動することです。これは、コンテナーのライフタイム マネージャーを変更することで非常に簡単に実行できますが、これにより、(おそらく) ワーカー スレッドがジョブ ステータスを「完了」に更新する同時実行性の問題が発生します。ただし、キャッシュされたコピーがまだ「進行中」であるため、メインスレッドは認識しません。

次のアプローチは、リクエストごとのコンテキストを持つことだと思いますが、特に多くのスレッドが並行して実行されている場合、多くのセットアップ/ティアダウンが発生するのではないかと心配しています。いずれにせよ、私はそれを試してみて、それがどれほど良い/悪いかを見ていきます.

最後のオプションが進むべき道であると仮定すると、Unity に同じコンテキストごとの論理リクエストを解決させるにはどうすればよいでしょうか? つまり、私がそうするなら...

Dim UnitOfWork = Container.Resolve(Of IUnitOfWork)
Dim UserRepo = Container.Resolve(Of IUserRepository)
Dim RoleRepo = Container.Resolve(Of IRoleRepository)
''Do Stuff
UnitOfWork.Commit

すべてのオブジェクトが同じコンテキストを使用する必要があります。自分のライフタイム マネージャーを作成し、各グループに固有のものを使用する必要がありますか (新しい Guid など)。

Dim Key = Guid.NewGuid
Dim UnitOfWork = Container.Resolve(Of IUnitOfWork)(New MyLifetimeManager(Key))
Dim UserRepo = Container.Resolve(Of IUserRepository)(New MyLifetimeManager(Key))

またはより良い方法はありますか?

4

1 に答える 1

1

いいえ、他のオブジェクトのプロバイダーとなる解決には、単一のトップレベル オブジェクトだけが必要です。例えば:

public interface IDalProvider
{
    IUnitOfWork { get; }
    IUserReposiotry { get; }
    ...
}

このインターフェイスの実装は、Unity によって解決されます。実装に実際に実装を作成させるか、依存性注入を介してそれらを渡すかは、あなた次第です。

前者の場合、コンテキスト インスタンスをプロバイダー実装に注入し、作業単位とリポジトリ インスタンスを構築するときに内部的に使用します。後者の場合、作業単位とリポジトリの実装にコンテキスト インスタンスを直接注入し、コンテキスト、uow、およびリポジトリに解決ごとの有​​効期間を使用します (単一の解決で同じインスタンスがすべての依存オブジェクトに注入されます)。

于 2012-06-25T10:05:00.497 に答える