0

У меня есть приложение, которое используется на двух разных сайтах. У каждого сайта есть своя база данных.Переключение DbContext на использование инъекции зависимостей Ninject на сеанс пользователя

Есть 2 DbContexts, 1 для каждого сайта. Когда пользователь открывает мое приложение, появляется всплывающая страница, где они выбирают свой сайт. После выбора сайта ядро ​​отскакивает, чтобы использовать DbContext для выбранного сайта.

private void RebindDbContext(string site) 
{ 
    switch (site) 
    { 
     case "Site1": 
      _kernel.Rebind<DbContext>().To<DbContext1>().InRequestScope(); 
      break; 
     case "Site2": 
      _kernel.Rebind<DbContext>().To<DbContext2>().InRequestScope(); 
      break; 
    } 
} 

Теперь для Боба & Мэри объяснения: Это прекрасно работает, когда Боб выбирает сайт 1. Но когда Мэри выбирает сайт 2. DbContext для Боба повторно связан с сайтом 2. То, что я хочу для Боба и Мэри можно использовать приложение одновременно, не затрагивая друг друга.

Я пробовал использовать TransientScope, ThreadScope и InRequest Scope, но ни один из них не работал.

Приложение выполняется на сервере IIS

Спасибо за любую помощь

+1

Как насчет использования поставщика ninject для этой цели? Или привязайтесь к методу вместо повторной привязки. – MaKCbIMKo

ответ

2

Наручники предназначены быть сделано один раз в применении, не зависит от состояния. В этом случае, у вас есть пара вариантов:

1) Ninject.Activation.IProvider

public class DbContextProvider : Ninject.Activation.IProvider 
{ 
    public Type Type 
    { 
     get { return typeof(DbContext); } 
    } 

    public object Create(IContext context) 
    { 
     var siteProvider = context.Kernel.Get<ISiteProvider>(); // use a provider to find which site is being used 
     switch (siteProvider.Current) 
     { 
      case "Site1": 
       return new DbContext1(); // or use a factory to create 
      case "Site2": 
       return new DbContext2(); 
     } 
    } 
} 

затем:

Bind<DbContext>().ToProvider<DbContextProvider>().InRequestScope(); 

2) Условные Binding

Модификатор When() имеет куча перегрузок для разных состояний, или вы могли бы c повторите метод расширения, если у вас есть один тип, который вы используете много.

 Bind<DbContext>().To<DbContext1>() 
      .When(request => request.ParentContext.Kernel.Get<ISiteProvider>().Current == "Site1") 
      .InRequestScope(); 

     Bind<DbContext>().To<DbContext2>() 
      .When(request => request.ParentContext.Kernel.Get<ISiteProvider>().Current == "Site2") 
      .InRequestScope(); 

Это хороший вариант, если у вас есть только несколько условий, которые могут применяться для этого связывания. Если ваша логика становится ЛЮБОЙ более сложной, чем это, обратитесь к провайдеру. Также обратите внимание, что условные привязки несут штраф за производительность.

3) ToMethod() Связывание

Для простейшей связывающей логики, вы можете иметь Ninject запустить код каждый раз, когда связывание Постановили:

Bind<DbContext>().ToMethod(context => 
      context.Kernel.Get<ISiteProvider>().GetSite()); 

В принципе, какой вариант выбрать, зависит от сколько логики участвует в принятии решения о том, какой экземпляр активируется. В каждом случае вы можете либо new() вверх экземпляр, или у вас есть доступ к Ikernel, в котором вы можете разрешить экземпляр:

context.Kernel.Get<DbContext2>(); 

вот некоторые официальные документы процесса активации:

https://github.com/ninject/Ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context

+0

Вариант 1 работал –