我有一个使用通用存储库模式进行数据访问的应用程序。由于应用程序需要使用几个不同的数据库,我使用Ninject Factory Extension实现了一个存储库工厂。这允许我按需为各种数据库创建存储库。我只是将DBContext传递给工厂,如下所示:
private readonly IRepository database1;
private readonly IRepository database2;
public MembershipService(IRepositoryFactory repositoryFactory)
{
this.database1 = repositoryFactory.CreateRepository(new Context("Database1"));
this.database2 = repositoryFactory.CreateRepository(new Context("Database2"));
}
这段代码令人讨厌的是创建Context所需的字符串。上例中的字符串“Database1”和“Database2”。如果在整个项目中使用上述代码很多次,那么简单的拼写错误就容易造成重大问题。
我该如何解决这种情况?我应该创建一个上下文工厂吗?那仍然需要数据库名称。我可以以某种方式使用枚举?我一直在抛弃一堆想法,但似乎没有什么比较合适
答案 0 :(得分:1)
在IRepositoryFactory的派生类上放置一个接受DbContext的构造函数
class RepositoryFactory : IRepositoryFactory
{
DbContext _dbc;
public RepositoryFactory(DbContext db)
{
_dbc = db;
}
public IRepository CreateRepository()
{
return new Repository(_dbc);
}
}
然后将NbContext绑定到Ninject注入绑定上,将其与其他绑定一起放置:
ninjectKernel.Bind<DbContext>().To<EfDbContext>().InRequestScope();
我只是在这里猜一下,这就是你对RepositoryFactory的注入绑定的样子:
ninjectKernel.Bind<IRepositoryFactory<Person>>().To<RepositoryFactory<Person>>();
如果你将这两个绑定彼此相邻(顺序并不重要),Ninject应该能够为RepositoryFactory的构造函数的DbContext参数注入值。
一个例子
在此处查看EF的存储库模式,第22行:http://code.google.com/p/to-the-efnh-x/source/browse/trunk/ToTheEfnhX/Ienablemuch.ToTheEfnhX.EntityFramework/EfRepository.cs
在此处查看NHibernate的存储库模式,第24行:http://code.google.com/p/to-the-efnh-x/source/browse/trunk/ToTheEfnhX/Ienablemuch.ToTheEfnhX.NHibernate/NhRepository.cs
我如何使用存储库模式抽象这两个不同的ORM,Ninject促进了连接的依赖注入(实体框架的DbContext,NHibernate的Session):
int target = 1; // memory, nhibernate, entity framework
switch (target)
{
case 0:
ninjectKernel.Bind<IRepository<Person>>().ToMethod(x =>
{
var person = new MemoryRepository<Person>();
person.Save(new Person { Username = "Hello", Firstname = "Yo", FavoriteNumber = 9 }, null);
person.Save(new Person { Username= "See", Firstname = "Nice" }, null);
return person;
}
).InSingletonScope();
break;
case 1:
ninjectKernel.Bind<ISession>().ToMethod(x => ModelsMapper.GetSessionFactory().OpenSession()).InRequestScope();
ninjectKernel.Bind<Ienablemuch.ToTheEfnhX.IRepository<Person>>().To<Ienablemuch.ToTheEfnhX.NHibernate.NhRepository<Person>>();
ninjectKernel.Bind<Ienablemuch.ToTheEfnhX.IRepository<Country>>().To<Ienablemuch.ToTheEfnhX.NHibernate.NhRepository<Country>>();
break;
case 2:
ninjectKernel.Bind<DbContext>().To<EfDbContext>().InRequestScope();
ninjectKernel.Bind<Ienablemuch.ToTheEfnhX.IRepository<Person>>().To<Ienablemuch.ToTheEfnhX.EntityFramework.EfRepository<Person>>();
ninjectKernel.Bind<Ienablemuch.ToTheEfnhX.IRepository<Country>>().To<Ienablemuch.ToTheEfnhX.EntityFramework.EfRepository<Country>>();
break;
default:
break;
}
答案 1 :(得分:0)
我的通用存储库模式存在同样的问题,以下是我如何解决它:
http://blog.staticvoid.co.nz/2012/01/multiple-repository-data-contexts-with.html
这允许我根据命名空间声明特定类型的存储库来自不同的数据库。
就使用而言,你可以去
public MembershipService(IRepository<User> userRepository, IRepository<AppRole> roleRepository)
其中User和AppRole来自单独的DBcontexts
答案 2 :(得分:0)
如果每个数据库都有不同的DbContext类型,则可以通过创建两个绑定来简化该过程:
kernel.Bind&LT;的 DatabaseDbContext1 强>&GT;()的 ToSelf 强>()InRequestScope();
kernel.Bind&LT;的 DatabaseDbContext2 强>&GT;()的 ToSelf 强>()InRequestScope();
在Repository构造函数中包含两种类型:
公共存储库( DbContext1,DbContext2 )
您不需要在DBContext构造函数中放置连接字符串名称。只需将每个连接字符串命名为与每个DbContext名称相同。 EntityFramework将解决剩下的问题。