C# 具有Ninject和Ninject工厂扩展的存储库。失去神奇的弦?

C# 具有Ninject和Ninject工厂扩展的存储库。失去神奇的弦?,c#,entity-framework,ninject,ninject-extensions,C#,Entity Framework,Ninject,Ninject Extensions,我有一个使用通用存储库模式进行数据访问的应用程序。由于应用程序需要使用多个不同的数据库,我使用Ninject工厂扩展实现了一个存储库工厂。这使我能够根据需要为各种数据库创建存储库。我只需将DBContext传递给工厂,如下所示: private readonly IRepository database1; private readonly IRepository database2; public MembershipService(IRepositoryFactor

我有一个使用通用存储库模式进行数据访问的应用程序。由于应用程序需要使用多个不同的数据库,我使用Ninject工厂扩展实现了一个存储库工厂。这使我能够根据需要为各种数据库创建存储库。我只需将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”。当上面的代码在整个项目中被多次使用时,一个简单的打字错误很容易导致重大问题


我怎样才能补救这种情况?我应该创建一个上下文工厂吗?这仍然需要数据库名称。我可以使用枚举吗?我已经讨论了很多想法,但似乎没有什么是完全合适的

将接受DbContext的构造函数放在IRepositoryFactory的派生类上

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();
ninjectKernel.Bind().To().InRequestScope();
我只是猜测一下,这是您针对RepositoryFactory的注入绑定的样子:

ninjectKernel.Bind<IRepositoryFactory<Person>>().To<RepositoryFactory<Person>>();
ninjectKernel.Bind().To();
如果将这两个绑定相邻(顺序不重要),Ninject应该能够向RepositoryFactory的构造函数的DbContext参数注入值


一个例子

请看第60至76行:

请参见此处的EF存储库模式,第22行:

请参见NHibernate的存储库模式,第24行:

我是如何用repository模式抽象出这两个不同的ORM的,连接的依赖注入(实体框架的DbContext,NHibernate的Session)是由Ninject实现的:

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;
}
int target=1;//内存,nhibernate,实体框架
交换机(目标)
{
案例0:
ninjectKernel.Bind().ToMethod(x=>
{
var person=newmemoryrepository();
保存(新的person{Username=“Hello”,Firstname=“Yo”,FavoriteNumber=9},空);
保存(新的person{Username=“See”,Firstname=“Nice”},null);
返回人;
}
).InSingletonScope();
打破
案例1:
ninjectKernel.Bind().ToMethod(x=>ModelsMapper.GetSessionFactory().OpenSession()).InRequestScope();
ninjectKernel.Bind().To();
ninjectKernel.Bind().To();
打破
案例2:
ninjectKernel.Bind().To().InRequestScope();
ninjectKernel.Bind().To();
ninjectKernel.Bind().To();
打破
违约:
打破
}

我的通用存储库模式也有同样的问题,以下是我解决问题的方法:

这允许我根据名称空间声明特定类型的存储库来自不同的数据库

在使用方面,你可以去

public MembershipService(IRepository<User> userRepository, IRepository<AppRole> roleRepository)
public membership服务(IRepository用户存储库、IRepository角色存储库)

如果User和AppRole来自不同的DbContext

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

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

kernel.Bind()

在存储库构造函数中,包括两种类型:

公共存储库(DbContext1、DbContext2

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