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

查看:28
本文介绍了从控制器配置连接字符串 (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);
        }
    }
}

helper 类如下所示:

Where the helper class looks like this:

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

示例 appsettings.json:

Example appsettings.json:

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

并在启动时注册:

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

该类的替代版本在哪里:

Where the alternative version of the class is:

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天全站免登陆