SharpRepository を Ninject と組み合わせて使用したいのですが、リポジトリ間でエンティティフレームワークの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 Started と SharpRepository:Configuration を読みましたが、どちらも私には役立ちません:
だから私の質問:誰かが私に上記の目標を達成するためのソースコード例のハウツーを提供できますか(DbContext
を拡張するすべてのリポジトリ間で1つのEntity Framework ConfigurationBasedRepository
インスタンスを共有する)?
まず、 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を直接使用できます。
まず、Jeff Tの回答で提供されるソリューションが機能します。
私は、ASP.NET MVC 4 + EF 5プロジェクトで Ninject を機能させるために実行した手順を完了します。次の例では、Specific Repositoryパターンが SharpRepository を介して実装されていることに言及することが重要です。
DbContext派生クラス を作成します。 _Domain.EfContext
_。それは
「コンテキストでの作業に推奨される方法」。
DbSet<T>
_をパブリックプロパティとして宣言します。 _public DbSet<Product> Products { get; set; }
_クラス_Domain.EfContext
_で次の2つのコンストラクターを宣言します。
_public EfContext() : base() {} public EfContext(string connectionName) : base(connectionName) {}
_
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.
}
_
Specific Repositoryを実装し、_SharpRepository.Repository.ConfigurationBasedRepository<T, TKey>
_から継承するクラスを定義します。例:
_public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{
// TODO Implement domain specific logic here.
}
_
コントローラーを作成します。 _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;
}
}
_
ファイル_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では不要)。