6

私はおそらく正しい方向に考えていません。私は、Dependency InjectionとASP.Net Coreについてはかなり新しいです。依存性注入によるバックグラウンドタスクのDbContext

私はASP.NetコアのWebサイトを持っており、Excelのシートからユーザーがアップロードするデータベースにデータをインポートする作業があります。 Excelシートは膨大なものになる可能性があり、データ変換タスクは時間を要するため、バックグラウンドで実行したいと考えています。すなわち、ユーザがシートをアップロードすると、応答は直ちに送信され、バックグラウンドジョブ/スレッドはデータをインポートする。

私はバックグラウンドジョブを実行しようとしています

:私はに実行し、問題がプロセスのインポート方法があるASP.Net依存性注入コンテナを経由してAppDbContextにアクセスするリポジトリのクラスを持ってサービスを呼び出すことです

Task.Run(() => ProcessImport(model)); 

Scopedとして追加され、応答が返されるとコンテキストが破棄されます。実行時例外が発生しましたが、その処理後にコンテキストを使用することはできません。

私の質問は、この状況を処理する最善の方法は何ですか?私はAppDbContextシングルトンを作るべきですか?私はProcessImportメソッドでAppDbContextの新しいインスタンスを作成し、それを渡す必要がありますか?私はDbContextはスレッドセーフではないので、それは良いアプローチですか?

+0

は "私はAppDbContextシングルトンを作るべきか?" Nope:https://stackoverflow.com/questions/3266295/net-entity-framework-and-transactions/3266481#3266481 – Steven

+0

あなたは正しいですが、DbContextにアクセスする必要がある別のスレッドで実行中のタスクを処理する方法はありますか? –

+3

これはとにかく危険なパターンです。 ASP.Netアプリケーションを使用して[長時間実行されるファイア&忘れたタスク](http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx)には使用しないでください。それを正しく行うと、タスクはそれ自身のプロセスで実行され、DIの問題全体はなくなります。 –

答えて

10

IServiceScopeFactoryインスタンス(これはシングルトン)をタスクに渡す必要があります。

データが到着すると、新しいCreateScope()を作成し、そのスコープからサービスを要求する必要があります。データ処理が終了したら、このスコープを破棄します(ただし、次の実行にはIServiceScopeFactoryを参照してください)。

たとえば、thisを参照してください。私はこのライブラリで小さくて速いタスクを実行します。

Gertが書いたように、重い/長時間の作業の場合は、タスクが常に完了するまで実行されないようにしてください。再始動の準備をして、同じデータを再処理する準備をしてください。ご質問破壊を

+0

私のシナリオでそれを適用する方法を完全に理解していません。私は、データベースからアクセスするためのリポジトリクラスを現在注入している、コントローラから呼び出されるImportServiceというクラスを持っています。これらのリポジトリクラスをProcessImportメソッドで使用したいと思います。 私が正しく理解していれば、(var scope = ServiceScopeFactory.CreateScope()) のメソッド本体を囲んでいると、ブロックの存続期間中に注入されたクラスが最後になるか、注入されますか? {} これらのクラスの新しいインスタンスですか? –

+0

いいえ、新しいスコープは、db(および他のスコープライフタイム)クラスの新しいインスタンスを提供します。ユーザー[要求]がProcessImportを完了するのを待たせたくない場合は、scope-lifetimeのインスタンスを共有するべきではありません。要求スコープは、要求終了時に廃棄され、その中にすべての使い捨てコンテンツが廃棄されます。 – Dmitry

3

  1. この状況に対処するための最良の方法は何ですか?

    長時間実行されるタスクをAPIで処理することは理想的ではありません。プロセスをバックグラウンドアプリケーションに委譲することができます

  2. 私はAppDbContextシングルトンを作るべきですか?

    dbContextは、トランザクション管理のような問題を引き起こす可能性があるため、Webアプリケーションのシナリオではシングルトンであってはなりません。

  3. この状況を処理する最善の方法は何ですか?

    内訳さまざまなサービス/プロセス:

    • ファイルがかかりますAPI。理想的には、APIはファイルを入力として取り出し、それをディスクまたはデータベースに保持するだけです。
    • ファイルを処理するサービス。このコンポーネント/サービスを別のライブラリとして作成します。その後、コンソールアプリケーションからこのライブラリを使用します。これにより、パフォーマンスをプロファイルできます。それを非同期メソッドにすることによって、メソッドを忘れてしまいます。これにより、コードを再利用する柔軟性が得られます。
    • 多くのファイルアップロードが必要ない場合は、APIコントローラでライブラリを再利用し、QueueBackgroundWorkItemを使用してメソッドを実行できます。参考のためにここを参照してください:http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
  4. 私はProcessImport方法でAppDbContextの新しいインスタンスを作成し、それに沿って渡すべきか?

    スレッドセーフではないため、各スレッドでdbContextクラスのインスタンスを個別に作成して使用してください。

  5. 私はDbContextはスレッドセーフではありませんので、それは良いアプローチですか? EF dbContextを使用しての詳細なガイドについては

    、このブログをチェックアウト:http://mehdi.me/ambient-dbcontext-in-ef6/