如何将实体框架DbContext注入SharpRepository的ConfigurationBasedReposito
本文关键字:注入 SharpRepository ConfigurationBasedReposito DbContext 框架 实体 | 更新日期: 2023-09-27 18:10:36
我真的很想将SharpRepository与Ninject一起使用,但我不知道如何配置Ninject以在存储库之间共享实体框架DbContext。
我使用的是EntityFramework版本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
{
// [...]
}
我已经读过SharpRepository:Getting Started和SharpRepository:Configuration这两篇博客文章,但它们都对我没有帮助,因为:
- 使用的DIC是StructureMap,而不是Ninject
- 源代码示例不完整(例如使用未声明的变量(
因此,我的问题是:有人能为我提供一些源代码示例,说明如何实现上述目标(在所有扩展ConfigurationBasedRepository
的存储库之间共享一个实体框架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<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的类型。如果执行此操作,则需要通过更改在自定义上下文中将Ninject设置为Bind。Bind<DbContext>((到。绑定<自定义上下文>((。但就像我通常说的那样,你可以直接使用DbContext而没有问题。
首先,Jeff T在答案中提供的解决方案有效!
我将总结我为使Ninject在ASP.NET MVC 4+EF 5项目中工作所采取的步骤。值得一提的是,特定存储库模式是通过以下示例中的SharpRepository实现的。
所需软件
- 通过NuGet安装Ninject和"Ninject.MVC3"(也安装"Ninject.Web.Common"(
- 通过NuGet安装SharpRepository、"SharpRepositoryforEF5"answers"SharpReservewithNinjectIOC">
定义存储库层
-
创建一个DbContext派生类,例如
Domain.EfContext
。这是"使用上下文的推荐方法"。
- 将所有必需的
DbSet<T>
声明为公共属性,例如public DbSet<Product> Products { get; set; }
-
在类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", 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. }
-
定义一个实现特定存储库并从
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; } }
通过依赖注入容器(DiC(Ninject设置依赖注入(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
部分使示例更加完整(我使用的是SQLServerLocalDB(。
<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结合起来并运行起来!
如果我采取了一个或多个不必要的步骤,或者您看到了改进示例中描述的架构的可能性,请给我一个答复。
顺便说一句,我不得不将dbContextType
属性添加到repository
部分以使其工作(与Jeff T的回答相反(。
编辑(2013-08-28(:删除了不必要的步骤(最新版本的SharpRepository不需要(。