将 DbContext 切换为使用每个用户会话的 Ninject 依赖注入

Switching a DbContext to using Ninject Dependency injection per user session

我有一个应用程序用于 2 个不同的站点。每个站点都有自己的数据库。

有 2 个 DbContext,每个站点 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;
    }
}

现在是 Bob & Mary 的解释: 这在 Bob 选择站点 1 时工作正常。但是当 Mary 选择站点 2 时。Bob 的 dbContext 重新绑定到站点 2。我想要的是 Bob 和 Mary 能够同时使用该应用程序而不影响彼此。

我尝试过使用 TransientScope、ThreadScope 和 InRequest Scope,但其中 none 有效。

应用程序正在 运行 IIS 服务器上

感谢您的帮助

绑定旨在为每个应用程序完成一次,不依赖于状态。在这种情况下,您有几个选择:

1) A 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) 条件绑定

When() 修饰符有一堆针对不同状态的重载,或者如果你经常使用一种类型,你可以创建一个扩展方法。

        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());

基本上,您选择哪个 select 取决于在决定激活哪个实例时涉及多少逻辑。在每个实例中,您都可以 new() 启动一个实例,或者您可以访问可以在其中解析实例的 IKernel:

context.Kernel.Get<DbContext2>();

这里有一些激活过程的官方文档:

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