2012-05-04 2 views
0

У меня есть приложение, которое использует общий шаблон репозитория для доступа к данным. Поскольку для приложения требуется использование нескольких разных баз данных, я реализовал фабрику хранилища, используя расширение Ninject Factory Extension. Это позволяет мне создавать репозитории для различных баз данных по требованию. Я просто передать DbContext на фабрику следующим образом:Репозиторий с Ninject и расширение Ninject Factory. Потерять магические струны?

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» в примере выше. Когда вышеупомянутый код используется много и много раз по всему проекту, слишком просто для простой опечатки вызвать серьезные проблемы.

Как я могу исправить эту ситуацию? Должен ли я создать фабрику контекста? Для этого все равно потребуется имя базы данных. Могу ли я как-то использовать Enums? Я бросил вокруг куча идей, но ничего, кажется, соответствует совсем верно

ответ

1

Поместите конструктор, который принимает DbContext на класс, производный от вашего IRepositoryFactory

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

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

Затем вы связываете, что DbContext на вашей инъекции Ninject переплеты, поставить это вместе с другими креплениями:

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

Я просто принимая догадку здесь, это то, как ваши привязок инъекции для RepositoryFactory выглядит следующим образом:

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

Если вы сделали эти две привязки рядом друг с другом (порядок не имеет значения), Ninject должен иметь возможность делать инъекцию значения в параметр DbContext вашего конструктора RepositoryFactory.


Пример

Посмотрите на линии 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 с хранилищем шаблон, инъекции depency для соединений (DbContext для Entity Framework, Session для NHibernate) способствует 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; 
} 
0

У меня была такая же проблема с моим родовым шаблон репозитория, вот как я ее решил:

http://blog.staticvoid.co.nz/2012/01/multiple-repository-data-contexts-with.html

Это позволяет мне объявлять репозитории конкретных типов на основе пространства имен, поступающего из разных баз данных.

С точки зрения использования, вы можете затем

public MembershipService(IRepository<User> userRepository, IRepository<AppRole> roleRepository) 

, где пользователь и AppRole приходят из раздельных DBcontexts

0

Если у вас есть другой тип DbContext для каждой базы данных, вы можете упростить процесс создания два крепления:

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

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

В Repository конструктору включают оба типа:

общественного Repository (DbContext1, DbContext2)

Вам не нужно поместить имя строки подключения в DbContext конструкторах. Просто укажите каждую строку подключения так же, как и каждое имя DbContext. Остальное будет работать над EntityFramework.

Смежные вопросы