web-dev-qa-db-ja.com

Entity FrameworkのDbContextをSharpRepositoryのConfigurationBasedRepositoryに挿入する方法

SharpRepositoryNinject と組み合わせて使用​​したいのですが、リポジトリ間でエンティティフレームワークのDbContextを共有するようにNinjectを構成する方法がわかりません。

Entity Frameworkバージョン5とNinjectバージョン3を使用しています。

現在、ソースコードでEf5Repositoryを使用していますが、ConfigurationBasedRepositoryに置き換えたいです。しかし、EF DbContextをリ​​ポジトリに渡す(または注入する)方法がわかりません。

例(現在の状態):

using SharpRepository.Repository;

public interface IProductRepository : IRepository<Product>
{
}

using SharpRepository.Ef5Repository;
using System.Data.Entity;

// TODO Tightly coupled to Ef5Repository.
public class ProductRepository : Ef5Repository<Product>, IProductRepository
{
    // TODO The DbContext has to be injected manually.
    public ProductRepository(DbContext context) : base(context)
    {
    }

    // [...]
}

目標:

using SharpRepository.Repository;

public interface IProductRepository : IRepository<Product>
{
}

public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{
    // [...]
}

私はすでに2つのブログ投稿 SharpRepository:Getting StartedSharpRepository:Configuration を読みましたが、どちらも私には役立ちません:

  1. 使用されるDICはNinjectではなく、StructureMapです。
  2. ソースコードの例は不完全です(例:宣言されていない変数の使用)。

だから私の質問:誰かが私に上記の目標を達成するためのソースコード例のハウツーを提供できますか(DbContextを拡張するすべてのリポジトリ間で1つのEntity Framework ConfigurationBasedRepositoryインスタンスを共有する)?

19
Florian Wolters

まず、 SharpRepository.Ioc.Ninject NuGetパッケージ をインストールする必要があります。ここには、Ninjectをフックして汎用リポジトリーのロードを処理し、SharpRepositoryが使用する依存関係リゾルバーを設定するための拡張メソッドがあります。

Ninjectバインディングルール(kernel.Bind <>へのすべての呼び出し)を設定している場合は、以下を追加する必要があります。

kernel.BindSharpRepository();

次に、Global.asax、App_Startコード、またはBootstrapperロジック(アプリケーションの起動コードを呼び出す場所)に、以下を追加する必要があります。

// kernel is the specific kernel that you are setting up all the binding for
RepositoryDependencyResolver.SetDependencyResolver(new NinjectDependencyResolver(kernel));

これにより、新しいDbContextを取得するときにこのNinjectカーネルを使用するようSharpRepositoryに指示します。

最後に、DbContext自体のバインドのルールを設定します。 Webアプリケーションを使用している場合は、ほとんどの場合、リクエストごとにDbContextのスコープを設定する必要があります。私は個人的にはNinjectを使用していませんが、- InRequestScope を使用するためのこのリファレンスを見つけました。あなたのコードは次のようになると思います:

kernel.Bind<DbContext>().To<MyCustomEfContext>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["MyCustomEfContext"].ConnectionString);

ほとんどの人はこの次のピースは必要ありませんが、CustomEfContextにカスタムロジックがある場合(たとえば、SaveChanges()への呼び出しをログオンするためのオーバーライドがある場合)、構成ファイルでカスタムコンテキストタイプを定義する必要がありますそのようです:

<repositories>
  <repository name="ef5Repository" connectionString="CustomEfContext" cachingStrategy="standardCachingStrategy" dbContextType="My.Data.CustomEfContext, My.Data" factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository" />
</repositories>

DbContextTypeは、完全な型の名前空間構文を使用して、使用しているカスタムDbContextの型を定義します。これを行う場合は、.Bind <DbContext>()を.Bind <CustomEfContext>()に変更して、カスタムコンテキストでNinjectをBindに設定する必要があります。しかし、通常言ったように、問題なくDbContextを直接使用できます。

16
Jeff Treuting

まず、Jeff Tの回答で提供されるソリューションが機能します。

私は、ASP.NET MVC 4 + EF 5プロジェクトで Ninject を機能させるために実行した手順を完了します。次の例では、Specific Repositoryパターンが SharpRepository を介して実装されていることに言及することが重要です。


必要なソフトウェア

  1. Ninject および "Ninject.MVC3"( "Ninject.Web.Common"もインストールします)を NuGet を介してインストールします。
  2. インストール SharpRepository 、「SharpRepository for EF5」、および「SharpRepository with Ninject IOC」を NuGet でインストールします。

Repositoryレイヤーを定義する

  1. DbContext派生クラス を作成します。 _Domain.EfContext_。それは

    「コンテキストでの作業に推奨される方法」。

    • 必要なすべての_DbSet<T>_をパブリックプロパティとして宣言します。 _public DbSet<Product> Products { get; set; }_
    • クラス_Domain.EfContext_で次の2つのコンストラクターを宣言します。

      _public EfContext() : base() {}
      public EfContext(string connectionName) : base(connectionName) {}
      _
  2. Specific Repositoryのインターフェースを定義します。例:

    _// TODO By extending IRepository, the interface implements default Create-Read-Update-Delete (CRUD) logic.
    // We can use "traits" to make the repository more "specific", e.g. via extending "ICanInsert".
    // https://github.com/SharpRepository/SharpRepository/blob/master/SharpRepository.Samples/HowToUseTraits.cs
    public interface IProjectRepository : IRepository<Project>
    {
        // TODO Add domain specific logic here.
    }
    _
  3. Specific Repositoryを実装し、_SharpRepository.Repository.ConfigurationBasedRepository<T, TKey>_から継承するクラスを定義します。例:

    _public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
    {
        // TODO Implement domain specific logic here.
    }
    _

Consumerレイヤーを定義する

  1. コントローラーを作成します。 _Controllers.ProductController_。

    _public class ProductController : Controller
    {
        private IProductRepository Repository { get; private set; }
    
        // TODO Will be used by the DiC.
        public ProductController(IProductRepository repository)
        {
            this.Repository = repository;
        }
    }
    _

Dependency Injection Container(DiC)Ninjectを介してDependency Injection(DI)をセットアップする

ファイル_App_Start/NinjectWebCommon.cs_はNinject.Web.Commonによって自動的に作成され、モジュールをロードして、クラスNinjectWebCommonのメソッドRegisterServices(IKernel kernel) : voidにサービスを登録できます。例のそのメソッドの完全なソースコードを次に示します。

_    private static void RegisterServices(IKernel kernel)
    {
        kernel.BindSharpRepository();
        RepositoryDependencyResolver.SetDependencyResolver(
            new NinjectDependencyResolver(kernel)
        );

        string connectionString = ConfigurationManager.ConnectionStrings["EfContext"].ConnectionString;
        kernel.Bind<DbContext>()
            .To<EfContext>()
            .InRequestScope()
            .WithConstructorArgument("connectionString", connectionString);

        kernel.Bind<IProductRepository>().To<ProductRepository>();
    }
_

_Web.config_で次のsharpRepositoryセクションを定義します。

_    <sharpRepository>
        <repositories default="ef5Repository">
            <repository name="ef5Repository"
                connectionString="EfContext"
                cachingStrategy="standardCachingStrategy"
                dbContextType="Domain.EfContext, Domain"
                factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository"
            />
        </repositories>
    </sharpRepository>
_

さらに、connectionStringsセクションで例を完成させます(私はSQL Server LocalDBを使用しています)。

_    <connectionStrings>
        <add name="EfContext" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=Domain;Integrated Security=True" />
    </connectionStrings>
_

この結論が他の人がASP.NET MVC 4をEntity Framework 5とSharpRepositoryと共に起動して実行するのに役立つことを願っています!

1つ以上の不要な手順を実行した場合、または例で説明したアーキテクチャを改善する可能性がある場合は、返信を残してください。

ところで、私はhaddbContextType属性をrepositoryセクションに追加して機能させます(ジェフTの答え)。


EDIT(2013-08-28):不要な手順を取り消しました(最新バージョンのSharpRepositoryでは不要)。

6
Florian Wolters