Asp.net mvc 如何根据请求使用Auto Fac实例更改实体框架中的连接?

Asp.net mvc 如何根据请求使用Auto Fac实例更改实体框架中的连接?,asp.net-mvc,entity-framework,code-first,autofac,Asp.net Mvc,Entity Framework,Code First,Autofac,我正在使用Autofac(DI)根据请求创建实例。像 public class UserController : BaseController { public CUsersController(ICUserService userService) { this.userService = userService; } } 所有的项目都很好,但我有一个场景,我需要在我的DBContext类中更改db连接,并使用相同的DBContext根据

我正在使用Autofac(DI)根据请求创建实例。像

 public class UserController : BaseController
{       
    public CUsersController(ICUserService userService)
    {
        this.userService = userService;
    }
}
所有的项目都很好,但我有一个场景,我需要在我的DBContext类中更改db连接,并使用相同的DBContext根据该数据库获取数据,因为我在基于SAS的应用程序中使用代码优先的方法

我的问题是,在执行MVC控制器构造函数时,Autfac根据请求创建了MyDBContext类的实例,在创建MyDBContext类的实例之前,我无法传递连接字符串

请给我任何建议


谢谢

我是通过类似于以下代码的方式实现这一点的(它是针对web api而不是mvc项目的,但应该很容易翻译)


有两个选项可用于将输入更改为构造对象

第一个选项是使用策略模式。我假设您可以在需要构建数据库上下文时确定运行时连接字符串(或其他值)是什么。将该逻辑放入接口实现中,如下所示:

public interface IConnectionStringProvider
{
  string GetConnectionString();
}

public class EnvironmentConnectionStringProvider : IConnectionStringProvider
{
  public string GetConnectionString()
  {
    return Environment.GetEnvironmentVariable("connection");
  }
}
var builder = new ContainerBuilder();
builder.RegisterType<EnvironmentConnectionStringProvider>()
       .As<IConnectionStringProvider>();
builder.Register(ctx => {
          var provider = ctx.Resolve<IConnectionStringProvider>();
          return new DbContext(provider.GetConnectionString());
        }).As<IDbContext>();
builder.RegisterType<DbContext>()
   .As<IDbContext>()
   .WithParameter(
     new ResolvedParameter(
       (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
       (pi, ctx) => Environment.GetEnvironmentVariable("connection")));
显然,您的逻辑可能无法从环境中获得。但关键是,逻辑确实知道如何获得它,并且您需要打包该逻辑

完成此操作后,可以将上下文创建注册为lambda,如下所示:

public interface IConnectionStringProvider
{
  string GetConnectionString();
}

public class EnvironmentConnectionStringProvider : IConnectionStringProvider
{
  public string GetConnectionString()
  {
    return Environment.GetEnvironmentVariable("connection");
  }
}
var builder = new ContainerBuilder();
builder.RegisterType<EnvironmentConnectionStringProvider>()
       .As<IConnectionStringProvider>();
builder.Register(ctx => {
          var provider = ctx.Resolve<IConnectionStringProvider>();
          return new DbContext(provider.GetConnectionString());
        }).As<IDbContext>();
builder.RegisterType<DbContext>()
   .As<IDbContext>()
   .WithParameter(
     new ResolvedParameter(
       (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
       (pi, ctx) => Environment.GetEnvironmentVariable("connection")));
var builder=newcontainerbuilder();
builder.RegisterType()
.As();
builder.Register(ctx=>{
var provider=ctx.Resolve();
返回新的DbContext(provider.GetConnectionString());
}).As();
每次解析上下文时,lambda都会运行并获取相应的连接字符串

第二个选项是在注册时使用参数。

参数用法可能如下所示:

public interface IConnectionStringProvider
{
  string GetConnectionString();
}

public class EnvironmentConnectionStringProvider : IConnectionStringProvider
{
  public string GetConnectionString()
  {
    return Environment.GetEnvironmentVariable("connection");
  }
}
var builder = new ContainerBuilder();
builder.RegisterType<EnvironmentConnectionStringProvider>()
       .As<IConnectionStringProvider>();
builder.Register(ctx => {
          var provider = ctx.Resolve<IConnectionStringProvider>();
          return new DbContext(provider.GetConnectionString());
        }).As<IDbContext>();
builder.RegisterType<DbContext>()
   .As<IDbContext>()
   .WithParameter(
     new ResolvedParameter(
       (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
       (pi, ctx) => Environment.GetEnvironmentVariable("connection")));
builder.RegisterType()
.As()
.带参数(
新解析参数(
(pi,ctx)=>pi.ParameterType==typeof(string)和&pi.Name==“configSectionName”,
(pi,ctx)=>Environment.GetEnvironmentVariable(“连接”);
您也可以将它们组合起来。您将看到,这里的
ResolvedParameter
选项包含
ParameterInfo
和一个上下文,您可以从中解决问题。您可以打包策略,然后使用参数而不是在lambda注册中应用它


在这两种机制之间,您应该拥有在构建/实例化期间根据需要切换连接字符串所需的工具。

感谢您的回复,但我已经在我的Global.ascx文件中完成了autofac注册。在autofac创建实例后,我需要修改或重新创建MyDBContext实例。谢谢!我在基于SAS的应用程序中工作。应用程序已根据其子域名连接到DB。在这个应用程序中,我有一个模块,超级管理员可以查看所有子应用程序的用户。下面是一个下拉列表,它显示我正在向服务器发送ajax数据请求。根据应用程序Id。我需要从该应用程序数据库获取用户。我正在使用Autofac,因此在向ASP.NET MVC控制器构造函数发出请求时,构造函数已创建了服务对象,服务已创建了DBContext对象,之后我无法根据app DB修改该连接。与其在已创建连接后尝试更改该连接,在创建时通过上述模式进行更改。只有在建立对象时,Autofac才会起作用。在那之后,所有的都是应用程序代码。Autofac中没有任何内容会说:“创建此对象,然后在我的一些应用程序代码运行后,给我一个回调,以便我可以重新创建该对象。”如果需要,您必须自定义它。如果我们知道连接字符串,上述模式将起作用。我将根据应用程序id获取db凭据,然后将其存储在会话中。使用此会话,我尝试在dbcontext类对象中传递连接。同样,Autofac提供的所有参数都是参数-或。甚至还有。但是没有“在Autofac已经运行之后交换这个东西”。您可能需要重新设计上下文的创建方式,以适应您的独特情况。不幸的是,这差不多是我能提供的帮助的极限了。你得到什么答案了吗?我也需要解决这个问题