配置来自控制器的连接字符串(ASP.NET Core MVC 2.1) [英] Configure connection string from controller (ASP.NET Core MVC 2.1)

查看:141
本文介绍了配置来自控制器的连接字符串(ASP.NET Core MVC 2.1)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从控制器配置连接字符串,但是我找不到任何函数来执行此操作.

I would like to configure the connection string from the controller, but I don't find any function to do it.

我有:

public class tstController : Controller
{
    private readonly contextTst _context;

    public tstController(contextTst context)
    {
        _context = context;
        _context.Database.**????**
    }
}

有可能吗?

非常感谢!

推荐答案

鉴于您要在构造函数中设置备用连接字符串这一事实,表明它是一个已知值.

Given the fact that you want to set an alternative connectionstring in the constructor, suggests that it is a known value.

要解决的问题是如何使用DI进行此操作.第一个提示是在搭建上下文时生成的代码:

The thing to solve is how to do this with DI. The first hint is the code that is generated when scaffolding the context:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
//#warning To protect potentially sensitive information in your
// connection string, you should move it out of source code.
// See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
        optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS;Database=MyDb;Trusted_Connection=True;");
    }
}

这意味着您可以使用默认配置(optionsBuilder.IsConfigured),并在启动时设置该值.但也可以在构造上使用替代方法.

This means that you can either use the default configuration (optionsBuilder.IsConfigured), setting the value at startup. But also use an alternative on construction.

代码将如下所示:

public partial class MyContext : DbContext
{
    private readonly string _connectionString;

    public MyContext(DbContextOptions<MyContext> options)
        : base(options)
    {
    }

    public MyContext(IOptions<DbConnectionInfo> dbConnectionInfo)
    {
        _connectionString = dbConnectionInfo.Value.MyContext;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_connectionString);
        }
    }
}

辅助类如下所示:

public class DbConnectionInfo
{
    public string MyContext { get; set; }
}

示例appsettings.json:

Example appsettings.json:

"ConnectionStrings": {
    "MyContext": "Server=.\\SQLEXPRESS;Database=MyDb;Trusted_Connection=True;"
  },

并在启动时同时注册两者:

And register both in startup:

services.Configure<DbConnectionInfo>(settings => configuration.GetSection("ConnectionStrings").Bind(settings));
services.AddScoped<MyContext>();

如果您不想从配置中读取连接字符串,而是根据中间件(例如,每个租户)进行设置,则可以使用相同的方法. 只需在构造上下文之前更新值即可.

If you don't want to read the connectionstring from the configuration but rather set it depending on middleware (e.g. per tenant), then you can use the same approach. Just update the value before the context is constructed.

更新:

使用依赖注入,您不必自己构造对象,而是将注册的对象/服务作为参数传递. DI将找出需要以什么顺序创建哪些对象.使用后,DI将以同样的方式处理这些物体.

With dependency injection you do not construct the objects yourself but you pass the registered object / service as a paramater. DI will figure out what objects need to be created in what order. In the same way the objects will be disposed by DI after use.

控制器知道"上下文的事实是因为DI自动将其添加为参数.上下文知道" DbConnectionInfo的事实是因为它已注册到DI.

The fact that the controller 'knows' the context, is because DI adds it automatically as the parameter. The fact that the context 'knows' the DbConnectionInfo is because it is registered to DI.

如果要更改DbConnectionInfo,则需要以适当的方式添加它.在您的情况下,您可以执行以下操作:

If you want to change the DbConnectionInfo then you need to add it in a proper way. In your case you could do something like this:

// Added as part of the example
services.AddHttpContextAccessor();
// Replace registration with this line:
services.AddScoped<DbConnectionInfo>();
// Register the DbContext
services.AddScoped<MyContext>();

该类的替代版本为:

public class DbConnectionInfo
{
    public string MyContext { get; set; }

    // Example injecting IHttpContextAccessor
    // On creating this class DI will inject 
    // the HttpContextAccessor as parameter
    public DbConnectionInfo(IHttpContextAccessor httpContextAccessor)
    {
        // Access the current request
        var request = httpContextAccessor.HttpContext.Request;

        // Access the current user (if authenticated)
        var user = httpContextAccessor.HttpContext.User;

        // Now you could get a value from a header, claim,
        // querystring or path and use that to set the value:

        MyContext = "";
    }
 }

在DbContext中有一个小的更改,在这种情况下,我们不使用IOptions:

And in the DbContext a small change, we don't use IOptions in this case:

public partial class MyContext : DbContext
{
    private readonly string _connectionString;

    public MyContext(DbConnectionInfo dbConnectionInfo)
    {
        _connectionString = dbConnectionInfo.MyContext;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder     optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_connectionString);
        }
    }
}

现在,每个请求的值都将在创建MyContext之前设置.

Now on each request the value will be set prior to creating MyContext.

这篇关于配置来自控制器的连接字符串(ASP.NET Core MVC 2.1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆