適切なキャッシュとdbContextの使い方を持つDIサービス

.net-core asp.net-core-mvc c# dependency-injection entity-framework-core

質問

素敵で清潔で適切なコードを作成したいので、基本的な質問はほとんどありません。私はGetNameサービスを持っています。 _dbContext_dbContextような他のDIサービスからのもの_cache

public Task<string> GetName(string title)
{
    var articleList = await _cache.GetOrCreate("CacheKey", entry =>
    {
        entry.SlidingExpiration = TimeSpan.FromSeconds(60 * 60);
        return _dbContext.Articles.ToListAsync;
    });

    var article = articleList.Where(c => c.Title == title).FirstOrDefault()

    if(article == null)
    {
        return "Non exist"
    }

    return article.Name();
}
  1. 公式ドキュメント私は追加する必要がありますので、我々はそのEFコンテキストはスレッドセーフではありません読み取ることができるawait中に戻った後GetOrCreate
  2. Singletonサービスとして設定し、アクションやカミソリビューで使用するのが適切でしょうか?
  3. 公式ドキュメントでは、DIサービス内の他のオブジェクトへのアクセスを許可するためだけに存在する「データ所有者」オブジェクトを避けることができます。私は私のサービスを見てその行について心配しています。

人気のある回答

EFコンテキストがスレッドセーフでないという事実は、async \ awaitには関係しないので、最初の質問はあまり意味がありません。とにかく、複数の論理操作に対して単一のEFコンテキストを再利用しないことが一般的なベストプラクティスです。マルチスレッドアプリケーションでは、通常、このルールに違反するとすぐに災害につながります。一度に1つのスレッドから同じEFコンテキストを使用すると、違反は予期しない動作につながる可能性があります。特に、長い間多くの操作で同じコンテキストを使用している場合。

ASP.NETでは、各要求には専用のスレッドがあり、各要求は長い間持続せず、各要求は通常単一の論理操作を表します。そのため、EFコンテキストは、通常、スコープされた存続時間で登録されます。つまり、各要求には、要求が終了したときに配置される個別のコンテキストがあります。ほとんどの場合、このパターンはうまく機能します(単一のhttp要求で多数のデータベース要求を持つ複雑なロジックを実行すると予期しない動作が発生する可能性があります)。私は個人的には、すべての操作にEFコンテキストの新しいインスタンスを使用する方が好きです(あなたの例では、EFコンテキストファクトリを注入し、 GetOrCreate本体内に新しいインスタンスを作成してすぐにGetOrCreateます)。しかし、これはあまり知られていません。

だから、各リクエストは別々のコンテキストを持っています(スコープ付きのライフタイムで登録されている場合)ので、一般的にはバックグラウンドスレッドを作成しないとそのインスタンスへのマルチスレッドアクセスについては気にしないでください。

あなたのキャッシュに保存するものはList<Article>はないので、あなたのメソッドはまだ間違っています。 Task<List<Acticle>>代わりにTask<List<Acticle>> 。メモリキャッシュでは、シリアル化は必要ありません。 Taskが明らかにシリアライズ可能ではないため、キャッシュプロバイダを変更するとすぐに問題が発生します。 GetOrCreateAsync使用してGetOrCreateAsyncreturn後にawaitを追加する理由はまだありません)。

var articleList = await _cache.GetOrCreateAsync("CacheKey", entry =>
{
    entry.SlidingExpiration = TimeSpan.FromSeconds(60 * 60);
    return _dbContext.Articles.ToListAsync();
});

行って何の非同期作業は存在しません、全体の動作を完全に同期的に実行されます(せてはいけない-アイテムがキャッシュ内に既に存在している場合がありますawaitあなたをだます-あなたがあればawait何かを、それが必要というわけではありませんいくつかのバックグラウンドスレッドがあるでしょうか非同期操作が含まれる)。

EFエンティティをキャッシュに直接格納するのは一般的には良いことではありません。それらをDTOエンティティに変換して格納する方が良いです。しかし、EFエンティティを格納している場合、少なくともあなたのコンテキストで遅延ロードとプロキシの作成を無効にすることを忘れないでください。

存続期間をスコープとするEFコンテキスト(デフォルト)に依存するため、シングルトンなどのサービスを登録することは適切ではありません。 EFの文脈と同じ生涯で登録してください。

「データ保持者」オブジェクト避けるために、私はそれがここでどのように関連しているのか分かりません。サービスにはロジック(キャッシュまたはデータベースからデータを取得)があります。他のオブジェクトへのアクセスを許可するためだけに存在するわけではありません。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ