如何将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 ,但它们都没有帮助我,因为:
- 使用的DIC是StructureMap,而不是Ninject。
- 源代码示例不完整(例如,使用未声明的变量)。
所以我的问题:有人能为我提供一些源代码示例如何实现上述目标(在扩展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
首先,Jeff T的答案中提供的解决方案是有效的!
我将总结我为使Ninject在ASP.NET MVC 4 + EF 5项目中工作所采取的步骤。 值得一提的是,在以下示例中,通过SharpRepository实现了特定存储库模式。
所需的软件
- 通过NuGet安装Ninject和“Ninject.MVC3”(也安装“Ninject.Web.Common”)。
- 通过NuGet安装SharpRepository ,“SharpRepository for EF5”和“SharpRepository with Ninject IOC”。
定义存储库层
-
创建一个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) {}
- 声明所有必需的
-
为特定存储库定义接口,例如:
// 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. } -
定义一个实现特定存储库的类,并inheritance自
SharpRepository.Repository.ConfigurationBasedRepository
,例如:public class ProductRepository : ConfigurationBasedRepository
, IProductRepository { // TODO Implement domain specific logic here. }
定义消费者层
-
创建一个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)。