n層Entity Frameworkソリューションによる依存性注入


12

現在、データアクセス戦略としてEntity Framework 5(.net 4)を使用しているn層ソリューションを設計していますが、依存性注入を組み込んでテスト可能/柔軟にする方法を検討しています。

私の現在のソリューションレイアウトは次のとおりです(私のソリューションはAlcatrazと呼ばれます)。

Alcatraz.WebUI:asp.net webformプロジェクト、フロントエンドユーザーインターフェイスは、プロジェクトAlcatraz.BusinessおよびAlcatraz.Data.Modelsを参照します。

Alcatraz.Business:クラスライブラリプロジェクト。ビジネスロジックを含み、プロジェクトAlcatraz.Data.AccessAlcatraz.Data.Modelsを参照します。

Alcatraz.Data.Access:クラスライブラリプロジェクトは、AlcatrazModel.edmxAlcatrazEntitiesDbContextを収容し、プロジェクトAlcatraz.Data.Modelsを参照します。

Alcatraz.Data.Models:クラスライブラリプロジェクト。AlcatrazモデルのPOCOを含み、参照はありません。

このソリューションがどのように機能するかについての私のビジョンは、web-uiがビジネスライブラリ内のリポジトリをインスタンス化することです。このリポジトリは(コンストラクタを介して)接続文字列(AlcatrazEntitiesインスタンスではなく)の依存関係を持ちます。web-uiはデータベース接続文字列を知っていますが、それがエンティティフレームワーク接続文字列であることはわかりません。

ビジネスプロジェクトで:

public class InmateRepository : IInmateRepository
{
    private string _connectionString;

    public InmateRepository(string connectionString)
    {
        if (connectionString == null)
        {
            throw new ArgumentNullException("connectionString");
        }

        EntityConnectionStringBuilder connectionBuilder = new EntityConnectionStringBuilder();

        connectionBuilder.Metadata = "res://*/AlcatrazModel.csdl|res://*/AlcatrazModel.ssdl|res://*/AlcatrazModel.msl";
        connectionBuilder.Provider = "System.Data.SqlClient";
        connectionBuilder.ProviderConnectionString = connectionString;

        _connectionString = connectionBuilder.ToString();
    }

    public IQueryable<Inmate> GetAllInmates()
    {
        AlcatrazEntities ents = new AlcatrazEntities(_connectionString);

        return ents.Inmates;
    }
}

Web UIの場合:

IInmateRepository inmateRepo = new InmateRepository(@"data source=MATTHEW-PC\SQLEXPRESS;initial catalog=Alcatraz;integrated security=True;");

List<Inmate> deathRowInmates = inmateRepo.GetAllInmates().Where(i => i.OnDeathRow).ToList();

この設計に関するいくつかの関連する質問があります。

  1. この設計は、Entity Frameworksの機能の観点からも理にかなっていますか?Entityフレームワークはすでに作業単位パターンを使用していると聞きましたが、抽象のレイヤーを不必要に追加しているだけですか?

  2. 私のWeb UIがEntity Frameworkと直接通信することを望まない(または、そのことを参照することさえ) (Webサービス、Windowsアプリケーションなど)、ビジネスロジックを1つの中央領域に配置することで、メンテナンスや更新を簡単に行えるようにしたいと考えています。これはこれを達成する適切な方法ですか?

  3. ビジネスレイヤーにリポジトリを含める必要がありますか、それともアクセスレイヤーに含める必要がありますか?どこに問題がなければ、接続文字列を渡すのは良い依存関係でしょうか?

読んでくれてありがとう!

回答:


11

DIのやり方は間違っています。

まず、接続文字列はデータレイヤーに属します。または、web.configファイル内。

次に扱う抽象概念は、接続文字列ではなく、DbContextです。リポジトリは接続文字列を知らないはずです。あなたのビジネスロジックはDbContextなどを知らないでしょう。

UIには何もわからず、EFに関連するものはインスタンス化されません。

あなたのポイントへの具体的な答え:

  1. EFに精通するまで、抽象化を追加しないでください。UoW、クエリ、POCOの使用などの優れた抽象化が既に追加されています。

  2. DIが機能するには、必要なすべてのコンポーネントを参照するコンポジションルートがあります。これは、WebUIプロジェクトに含まれている場合と含まれていない場合があります。そうでない場合は、EFまたはその他のデータ関連技術を参照していないことを期待する必要があります。

  3. ここでやめて 抽象化に対する抽象化の追加を停止します。直接的な「単純な」アーキテクチャから始めて、時間をかけて開発します。

抽象化は、複雑さに対処するためのツールです。複雑さがないということは、抽象化がまだ必要ないことを意味します。


あなたが言っていることを理解していることを明確にするために:リポジトリ(インターフェイスはビジネスに存在し、コンクリートはAlcatraz.Data.Accessに存在しますか?)はDbContext依存関係としてaを受け入れます。ビジネスクラスには、依存関係としてリポジトリがあります。依存性注入では、これを手動で実行しています(そのため、何が起こっているのか理解できます)。接続文字列を設定できるようにしたい理由は、DbContextデータベースシャーディングを使用しているため、特定のケースでは(同じ構造の)異なるデータベースに接続するためのエンティティフレームワークが必要だからです。あなたを正しく理解していますか?
マシュー

あなたが提供したコードから、DIをまったく行っていないようです。DIの主な目的は、あなたとあなたのコードが依存関係を管理することから解放することです。DIコンテナなしで手動で効果的に行うことは想像できません。
ボリスヤンコフ

また、DIで心を開いてください。私はすでに、楽しみのために、ここでまったく同じ質問をし、反対の答えを得るために他のフォーラムで尋ねました。DIはパターンであり、アーキテクチャではありません。目的に応じて、使用するかどうかを決定できます。私はそれを使用しますが、ほとんどの人がそれを使用するように私に言う理由のためではありません。
バスティアンヴァンダム

4

いくつかの簡単なコメント。個人的には、接続文字列を渡さないでしょう。リポジトリ用のインターフェイスを作成して、インターフェイスを作成する場合はどうすればよいですか?リポジトリにIOWインターフェイスを実装または公開します。

このように、イベントがリポジトリを実装するデータベースである必要はありません。それらは、メモリ内キャッシュ、またはその他の可能性があります。おそらく、何らかの依存性注入フレームワークを使用してこれらをインスタンス化することもできますか?

あなたの質問のいくつかに答えて:

  1. はい、大丈夫だと思います
  2. 私はまだEFプロジェクトを参照するUIと、EFリポジトリ層が実装するビジネス層参照インターフェイスを持っています。そうすれば、他のプロジェクトでも同じアセンブリを使用できますが、必要に応じて交換できる柔軟性がありますか?
  3. うーん、おそらくアクセス層のリポジトリですが、ビジネス層で公開されているインターフェース定義を実装していますか?

これらは熟考するための単なる考えです。


ポイント2について、私がやろうとしていた目標の1つは、UIレイヤー内にCRUDを直接持たないことです。つまり、ビジネスレイヤーを通過することでCRUDのみが発生し、そのように管理されるようにしたいのです。
マシュー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.