3

Service クラス (ASP.NET MVC アプリケーション内) の現在の取得パターンは次のようになります。

public Client Get(int id)
{
    using (var repo = _repoFactory.Get<Client>())
    {
        return repo.Get(id);
    }
}

Where_repoFactory.Get<T>()は、破棄されると Entity Framework も破棄するリポジトリを返しますDbContext

ただし、Get(int id)メソッドのコンシューマーがオブジェクトでナビゲーション プロパティを使用する必要がClientある場合は、コンテキストが既に破棄されているため、例外がスローされます。

この問題を交渉するいくつかの方法を予見できます。

  • サービス外でナビゲーション プロパティを使用しないでください
  • 遅延読み込みナビゲーション プロパティを使用しない
  • リクエストが終了したときにコンテキストを破棄する別の方法を見つける

「正しい」(または最も間違っていない)方法とは何ですか?

4

1 に答える 1

5

あなたが提案したすべての方法は「正しい」ものであり、それぞれに長所と短所があります。使用するアプローチを決定する必要があります。

サービス外でナビゲーション プロパティを使用しないでください

サービスがエンティティを返す場合、これを強制するのは困難です。私の現在のプロジェクトでは、「DTO」を多用しています。これは、特定のコンテキストで必要になると予想されるデータを表す新しいクラスです。これらはエンティティではないため、それらのプロパティはリポジトリから返される前に完全にハイドレートされることがわかっています。

遅延読み込みナビゲーション プロパティを使用しない

これは上記とほぼ同じですが、特定のナビゲーション プロパティを熱心にロードできるようにしている点が異なります。繰り返しますが、このデータを使用する開発者は、どのプロパティが利用可能であり、利用できないかをどのように知るのでしょうか? 「DTO」はこの問題を解決しますが、既存のエンティティとほとんど同じである余分なクラスの束も導入します。

リクエストが終了したときにコンテキストを破棄する別の方法を見つける

通常、DI フレームワークのリクエストごとのスコープにコンテキストをバインドすることでこれを行い、DI フレームワークがコンテキストのインスタンス化/破棄を処理できるようにします。

このアプローチの主な危険性は、遅延読み込みプロパティはアクセス時に例外をスローしませんが、アクセスごとに別のデータベース ラウンドトリップが必要になることです。これにより、開発者は、そうでなければ 2 つまたは 3 つのラウンドトリップしか必要とされない場合に、最終的に何千ものラウンドトリップを行うコードを誤って作成することが容易になります。

ただし、パフォーマンスの問題を特定して対処する信頼できる方法がある場合は、一般的なケースでこのアプローチを使用してから、必要に応じて少し熱心な読み込みを追加できます。たとえば、MiniProfilerをフロントエンドに配置して、実行中のデータベース ラウンドトリップに関する情報を提供したり、多くのデータベース クエリが実質的に同一であることに気付いた場合に警告を表示したりできます。

于 2013-11-13T17:35:16.483 に答える