web-dev-qa-db-ja.com

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

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

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

Alcatraz.WebUI:フロントエンドユーザーインターフェイスであるasp.net Webformプロジェクトは、プロジェクトAlcatraz.BusinessおよびAlcatraz.Data.Models

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

Alcatraz.Data.Access:クラスライブラリプロジェクト、住宅AlcatrazModel.edmxおよびAlcatrazEntities DbContext、プロジェクトAlcatraz.Data.Models

Alcatraz.Data.Models:クラスライブラリプロジェクト。参照なしで、アルカトラズモデルの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. ビジネス層にリポジトリを含める必要がありますか、それともアクセス層内に含める必要がありますか?それらがどこにあるかが問題ない場合、接続文字列を渡すことは仮定するのに良い依存関係ですか?

お読みいただきありがとうございます。

12
Matthew

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

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

次に扱う抽象化は、接続文字列ではなくDbContextです。リポジトリは接続文字列を知らないはずです。ビジネスロジックはDbContextなどを認識しません。

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

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

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

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

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

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

11
Boris Yankov

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

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

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

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

これらは、熟考するためのいくつかの考えにすぎません。

4
dreza