我真的想将SharpRepository与Ninject一起使用,但我不明白如何配置Ninject以在存储库之间共享Entity Framework DbContext。
我使用的是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
{
// [...]
}
我已经阅读了两篇博文SharpRepository: Getting Started和SharpRepository: Configuration,但他们都没有帮助我,因为:
所以我的问题:有人能为我提供一些源代码示例,以实现上述目标(在扩展DbContext
的所有存储库之间共享一个实体框架ConfigurationBasedRepository
实例)?
答案 0 :(得分:16)
首先,您需要安装SharpRepository.Ioc.Ninject NuGet package。这里有一些扩展方法,用于连接Ninject以处理加载通用存储库和设置SharpRepository使用的依赖解析器。
无论您在哪里设置Ninject绑定规则(对kernel.Bind&lt;&gt;的所有调用),您都需要添加:
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的类型。如果你这样做,那么你需要通过将.Bind&lt; DbContext&gt;()更改为.Bind&lt; CustomEfContext&gt;()来将Ninject设置为自定义上下文。但就像我通常说的那样,你可以直接使用DbContext而不会出现问题。
答案 1 :(得分:6)
首先,Jeff T在答案中提供的解决方案有效!
我将结束我在ASP.NET MVC 4 + EF 5项目中使Ninject工作的步骤。值得一提的是,特定存储库模式是通过以下示例中的SharpRepository实现的。
创建DbContext derived class,例如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;
}
}
文件App_Start/NinjectWebCommon.cs
由Ninject.Web.Common自动创建,我们可以加载我们的模块并在类RegisterServices(IKernel kernel) : void
的方法NinjectWebCommon
中注册我们的服务。
以下是该示例的完整源代码示例:
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>();
}
在sharpRepository
中定义以下Web.config
部分:
<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一起运行起来!
如果我采取了一个或多个不必要的步骤,或者您认为有可能改进示例中描述的架构,请给我回复。
<击>
顺便说一句,我已将dbContextType
属性添加到repository
部分以使其正常工作(与Jeff T的答案形成对比)。
击>
编辑(2013-08-28):删除了不必要的步骤(不需要最新版本的SharpRepository)。