Я пытаюсь реализовать веб-приложение с использованием ASP.NET MVC и инфраструктуры Microsoft Unity DI.Приложение должно поддерживать несколько пользовательских сессий одновременно, каждый из которых имеет свое собственное соединение с отдельной базой данных (но все пользователи используют один и тот же DbContext; схемы базы данных идентичны, это разные данные).
После входа пользователя в систему я регистрирую необходимые сопоставления типов в контейнере Unity приложения , используя основанный на сеансе диспетчер времени жизни, который я нашел в другом вопросе .
Мой контейнер инициализируется следующим образом:
// Global.asax.cs
public static UnityContainer CurrentUnityContainer { get; set; }
protected void Application_Start()
{
// ...other code...
CurrentUnityContainer = UnityConfig.Initialize();
// misc services - nothing data access related, apart from the fact that they all depend on IRepository<ClientContext>
UnityConfig.RegisterComponents(CurrentUnityContainer);
}
// UnityConfig.cs
public static UnityContainer Initialize()
{
UnityContainer container = new UnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
return container;
}
Это код, который вызывается при входе в систему:
// UserController.cs
UnityConfig.RegisterUserDataAccess(MvcApplication.CurrentUnityContainer, UserData.Get(model.AzureUID).CurrentDatabase);
// UnityConfig.cs
public static void RegisterUserDataAccess(IUnityContainer container, string databaseName)
{
container.AddExtension(new DataAccessDependencies(databaseName));
}
// DataAccessDependencies.cs
public class DataAccessDependencies : UnityContainerExtension
{
private readonly string _databaseName;
public DataAccessDependencies(string databaseName)
{
_databaseName = databaseName;
}
protected override void Initialize()
{
IConfigurationBuilder configurationBuilder = Container.Resolve<IConfigurationBuilder>();
Container.RegisterType<ClientContext>(new SessionLifetimeManager(), new InjectionConstructor(configurationBuilder.GetConnectionString(_databaseName)));
Container.RegisterType<IRepository<ClientContext>, RepositoryService<ClientContext>>(new SessionLifetimeManager());
}
}
// SessionLifetimeManager.cs
public class SessionLifetimeManager : LifetimeManager
{
private readonly string _key = Guid.NewGuid().ToString();
public override void RemoveValue(ILifetimeContainer container = null)
{
HttpContext.Current.Session.Remove(_key);
}
public override void SetValue(object newValue, ILifetimeContainer container = null)
{
HttpContext.Current.Session[_key] = newValue;
}
public override object GetValue(ILifetimeContainer container = null)
{
return HttpContext.Current.Session[_key];
}
protected override LifetimeManager OnCreateLifetimeManager()
{
return new SessionLifetimeManager();
}
}
Это прекрасно работает, если только один пользовательзарегестрирован за один раз.Данные извлекаются правильно, информационные панели работают, как и ожидалось, и все становится очень увлекательным.
Затем, как только второй пользователь входит в систему, происходит авария.
Последний пользователь, предложивший запросвызов RegisterUserDataAccess
, кажется, всегда имеет «приоритет»;их данные отображаются на приборной панели и ничего больше .Независимо от того, инициировано ли это входом в систему или выбором доступа к базе данных в моем веб-приложении, которое вызывает тот же метод для перенаправления подключения пользователя к другой базе данных, к которой у него есть права доступа, последняя из рисовавших всегда навязывает свои данные.на всех других пользователей веб-приложения.Если я правильно понимаю, это проблема, которую SessionLifetimeManager должен был решить - к сожалению, я действительно не могу заставить ее работать.
Я искренне сомневаюсь, что такой простой и распространенный пример использования -несколько пользователей, вошедших в приложение MVC, каждый из которых должен иметь доступ к своим собственным отдельным данным, находится за пределами возможностей Unity, поэтому, очевидно, я должен что-то здесь делать очень неправильно.Потратив большую часть моего дня на поиск в недрах Интернета, я даже не был уверен, что он действительно существует, но, к сожалению, теперь я должен осознавать, что нахожусь в полной и полной потере.
Кто-нибудь имел дело с этим?вопрос раньше?Кто-нибудь имел дело с этим вариантом использования раньше, и если да, может ли кто-нибудь сказать мне, как изменить мой подход, чтобы сделать это немного менее вызывающим головную боль?Я совершенно отчаялся в этом и собираюсь переписать всю мою методологию доступа к данным, просто чтобы она заработала - не самый здоровый образ мыслей для чистого и поддерживаемого кода.
Большое спасибо.