如何将Entity Framework DbContext注入SharpRepository的ConfigurationBasedRepository

我真的想将SharpRepository与Ninject一起使用,但我不明白如何配置Ninject以在存储库之间共享Entity Framework DbContext。

我正在使用Entity Framework版本5和Ninject版本3。

目前我在源代码中使用Ef5Repository ,但我想用ConfigurationBasedRepository替换它。 但我无法弄清楚如何将EF DbContext传递(或注入)到存储库。

示例(当前状态):

 using SharpRepository.Repository; public interface IProductRepository : IRepository { } using SharpRepository.Ef5Repository; using System.Data.Entity; // TODO Tightly coupled to Ef5Repository. public class ProductRepository : Ef5Repository, IProductRepository { // TODO The DbContext has to be injected manually. public ProductRepository(DbContext context) : base(context) { } // [...] } 

目标:

 using SharpRepository.Repository; public interface IProductRepository : IRepository { } public class ProductRepository : ConfigurationBasedRepository, IProductRepository { // [...] } 

我已经阅读了两篇博文SharpRepository:Getting Started和SharpRepository:Configuration ,但它们都没有帮助我,因为:

  1. 使用的DIC是StructureMap,而不是Ninject。
  2. 源代码示例不完整(例如,使用未声明的变量)。

所以我的问题:有人能为我提供一些源代码示例如何实现上述目标(在扩展ConfigurationBasedRepository所有存储库之间共享一个Entity Framework DbContext实例)?

首先,您需要安装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)); 

这将告诉SharpRepository在获取新的DbContext时使用此Ninject内核。

最后要做的是为DbContext本身设置绑定规则。 如果您在Web应用程序中,则很可能希望DbContext的范围是按请求进行的。 我个人不使用Ninject,但我找到了使用InRequestScope的参考资料 。 我相信你的代码看起来像这样:

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

大多数人不需要下一篇文章,但如果你的CustomEfContext中有自定义逻辑(我有一个覆盖用于登录对SaveChanges()的调用),那么你需要在配置文件中定义自定义上下文类型像这样:

    

其中dbContextType使用完整类型命名空间语法定义您正在使用的自定义DbContext的类型。 如果你这样做,那么你需要通过将.Bind ()更改为.Bind ()来将Ninject设置为自定义上下文。 但正如我通常说的那样,您可以直接使用DbContext而不会出现问题。

首先,Jeff T的答案中提供的解决方案是有效的!

我将总结我为使Ninject在ASP.NET MVC 4 + EF 5项目中工作所采取的步骤。 值得一提的是,在以下示例中,通过SharpRepository实现了特定存储库模式。


所需的软件

  1. 通过NuGet安装Ninject和“Ninject.MVC3”(也安装“Ninject.Web.Common”)。
  2. 通过NuGet安装SharpRepository ,“SharpRepository for EF5”和“SharpRepository with Ninject IOC”。

定义存储库

  1. 创建一个DbContext派生类 ,例如Domain.EfContext 。 它是

    “推荐使用上下文的方式”。

    • 声明所有必需的DbSet作为公共属性,例如public DbSet Products { get; set; } public DbSet Products { get; set; }
    • Domain.EfContext类中声明以下两个构造Domain.EfContext

       public EfContext() : base() {} public EfContext(string connectionName) : base(connectionName) {} 

  2. 特定存储库定义接口,例如:

     // TODO By extending IRepository, the interface implements default Create-Read-Update-Delete (CRUD) logic. // We can use "traits" to make the repository more "specific", eg via extending "ICanInsert". // https://github.com/SharpRepository/SharpRepository/blob/master/SharpRepository.Samples/HowToUseTraits.cs public interface IProjectRepository : IRepository { // TODO Add domain specific logic here. } 
  3. 定义一个实现特定存储库的类,并inheritance自SharpRepository.Repository.ConfigurationBasedRepository ,例如:

     public class ProductRepository : ConfigurationBasedRepository, IProductRepository { // TODO Implement domain specific logic here. } 

定义消费者

  1. 创建一个Controller,例如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容器(DiC)Ninject设置dependency injection(DI)

文件App_Start/NinjectWebCommon.cs由Ninject.Web.Common自动创建,我们可以加载我们的模块并在RegisterServices(IKernel kernel) : void方法中RegisterServices(IKernel kernel) : void我们的服务RegisterServices(IKernel kernel) : void NinjectWebCommon类的NinjectWebCommon 。 以下是该示例的完整源代码示例:

  private static void RegisterServices(IKernel kernel) { kernel.BindSharpRepository(); RepositoryDependencyResolver.SetDependencyResolver( new NinjectDependencyResolver(kernel) ); string connectionString = ConfigurationManager.ConnectionStrings["EfContext"].ConnectionString; kernel.Bind() .To() .InRequestScope() .WithConstructorArgument("connectionString", connectionString); kernel.Bind().To(); } 

Web.config定义以下sharpRepository部分:

       

另外, connectionStrings部分使示例完整(我使用的是SQL Server LocalDB)。

     

我希望这个结论能帮助其他人将ASP.NET MVC 4与Entity Framework 5和SharpRepository一起运行起来!

如果我采取了一个或多个不必要的步骤,或者您看到了改进示例中描述的架构的可能性,请给我回复。

顺便说一句,我不得不dbContextType属性添加到repository部分以使其工作(与Jeff T的答案形成对比)。


编辑(2013-08-28):敲定了不必要的步骤(不需要最新版本的SharpRepository)。