0

我有一个使用通用存储库模式进行数据访问的应用程序。由于应用程序需要使用几个不同的数据库,我使用 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"));
    }

这段代码令人讨厌的是创建上下文所需的字符串。上例中的字符串“Database1”和“Database2”。当在整个项目中多次使用上述代码时,一个简单的错字很容易导致重大问题。

我该如何补救这种情况?我应该创建一个上下文工厂吗?那仍然需要数据库名称。我可以以某种方式使用枚举吗?我一直在折腾一堆想法,但似乎没有什么合适的

4

3 回答 3

1

在 IRepositoryFactory 的派生类上放置一个接受 DbContext 的构造函数

class RepositoryFactory : IRepositoryFactory
{
    DbContext _dbc;
    public RepositoryFactory(DbContext db)
    {
       _dbc = db;
    }

    public IRepository CreateRepository()
    {
        return new Repository(_dbc);
    }
}

然后你在你的 Ninject 注入绑定上绑定那个 DbContext,把它和你的其他绑定放在一起:

ninjectKernel.Bind<DbContext>().To<EfDbContext>().InRequestScope();

我只是在这里猜测一下,这就是 RepositoryFactory 的注入绑定的样子:

ninjectKernel.Bind<IRepositoryFactory<Person>>().To<RepositoryFactory<Person>>();

如果您将这两个绑定彼此相邻(顺序并不重要),Ninject 应该能够向您的 RepositoryFactory 构造函数的 DbContext 参数注入值。


一个例子

在此处查看第 60 至 76 行:http ://code.google.com/p/flexigrid-crud-example/source/browse/trunk/FlexigridCrudDemo/FlexigridCrudDemo/NinjectDependencyResolver.cs

请参阅此处的 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 的会话):

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;
}
于 2012-05-04T03:04:47.213 回答
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

于 2012-05-04T03:11:29.697 回答
0

如果每个数据库都有不同的 DbContext 类型,则可以通过创建两个绑定来简化该过程:

kernel.Bind< DatabaseDbContext1 >()。ToSelf ().InRequestScope();

kernel.Bind< DatabaseDbContext2 >()。ToSelf ().InRequestScope();

在 Repository 构造函数中包括两种类型:

公共存储库(DbContext1,DbContext2

您不需要将连接字符串名称放在 DBContext 构造函数中。只需将每个连接字符串命名为与每个 DbContext 名称相同。EntityFramework 将解决剩下的问题。

于 2014-10-02T01:07:58.293 回答