.NET Core WebApp,多域,根据主机名更改SQL连接字符串,无法将httpcontext注入DB Context.cs文件

Ral*_*ama 1 entity-framework asp.net-core-mvc azure-web-app-service asp.net-core

我正在使用 Azure .NET 核心 WebApp、MVC、实体框架,搭建在现有的外部 MS SQL 数据库中。

我在启动 ConfigureServices 中注册数据库,如下所示:

services.AddDbContext<MyDbContext>(options => options.UseSqlServer());
Run Code Online (Sandbox Code Playgroud)

只要我在 MyDbContext.cs OnConfiguring() 方法中设置连接字符串,它就可以正常工作:

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
                optionsBuilder.UseSqlServer("Server=10.10.10.10;Database=MyDb;user id=username;password=password;");
        } 
Run Code Online (Sandbox Code Playgroud)

然后我可以简单地在控制器中说:

        private readonly MyDbContext _context;
        public HomeController()
        {
            _context = new MyDbContext();
        }

        public IActionResult Index()
        {
            var item = _context.TableName.FirstOrDefault(d => d.Id > 0);
        }
Run Code Online (Sandbox Code Playgroud)

这工作正常 - 数据流入。

我的问题是我需要根据连接的主机名更改 SQL 连接字符串。因此,无论是在启动 ConfigureServices() 中,如果我可以建立正在使用的主机名,我都可以传递连接,或者在 DB 的 MyDbContext.cs 文件的 OnConfiguring() 方法中。

我只能从 httpcontext 获取主机名,据我所知,在启动时无法查询?

如果我尝试将其注入 context.cs DB 文件,如下所示:

    public partial class MyDbContext : DbContext
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public MyDbContext()
        {
        }

        public MyDbContext(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;         // For context/url
        }

        public MyDbContext(DbContextOptions<MyDbContext> options, IHttpContextAccessor httpContextAccessor)
            : base(options)
        {
            _httpContextAccessor = httpContextAccessor;         // For context/url
        }
Run Code Online (Sandbox Code Playgroud)

然后启动 ConfigureServices 行 services.AddDbContext 无法传递 httpcontext(当时它不存在?)没有任何构造函数方法匹配 - 无论我如何尝试,我都无法将 IHttpContextAccessor httpContextAccessor 注入到 DB 上下文方法中!

services.AddDbContext<MyDbContext>(options => options.UseSqlServer("some-connection-string")); // Doesn't pass httpcontext
services.AddDbContext<MyDbContext>()); // Doesn't pass httpcontext
services.AddDbContext<MyDbContext>(is there way to pass it?); 

Run Code Online (Sandbox Code Playgroud)

它似乎不像将它注入控制器那样工作,因为那里没有构造函数,所以工作正常......

关于如何找到主机名并在给定此设置的情况下更改 SQL 连接字符串的任何想法?

出于各种原因,这需要是多个域顺便使用的单个 WebApp。

编辑

经过一个不眠之夜,我醒来并决定简单地连接到我需要的所有(三个)数据库,然后决定在控制器中使用哪个上下文,因为我在那里有 httpcontext 来决定哪个主机正在连接。这并不理想,但这是一个低开销的 WebApp,所以我很高兴能像这样使用它。我想也许那里有/曾经有一个解决方案......

Kne*_*lis 6

这是我一直用于多租户解决方案(客户拥有自己的数据库)的方法。

使用此构造函数签名创建上下文(不需要OnConfiguring):

public class MyDbContext : DbContext
{
    public MyDbContext(DbContextOptions<MyDbContext> options)
        : base(options) { }
}
Run Code Online (Sandbox Code Playgroud)

在您的 Startup 中,您需要注册您的上下文,我们现在可以添加一个解析器来获取正确的连接设置:

services.AddHttpContextAccessor();
services.AddDbContext<MyDbContext>();

// This registers DbContextOptions<MyDbContext> which will be called when a new
// instance of MyDbContext is created. You could set breakpoints in this method.
services.AddScoped(sp => 
{
    var context = sp.GetRequiredService<IHttpContextAccessor>().HttpContext;

    // your logic to determine connection string or EF provider
    // ...

    var builder = new DbContextOptionsBuilder<MyDbContext>();
    builder.UseSqlServer("connection string");

    return builder.Options;
});
Run Code Online (Sandbox Code Playgroud)