ASP.NET 从配置文件中读取的数据库上下文的核心 运行 迁移 (appsettings.json)

ASP.NET Core run migration for a database context that reads from the configuration file (appsettings.json)

我正在玩 ASP.NET 核心 1.1 应用程序,我正在尝试从配置文件中读取连接字符串。

我的数据库上下文 class 如下所示:

public class ApplicationDbContext : DbContext, IDbContextFactory<ApplicationDbContext>
{
    public ApplicationDbContext()
    {
    }

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

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }

    public ApplicationDbContext Create(DbContextFactoryOptions options)
    {
        var builder = new DbContextOptionsBuilder<ApplicationDbContext>();

        string connString = "some hardcoded connection string";
        builder.UseSqlServer(connString);
        return new ApplicationDbContext(builder.Options);
    }
}

运行 迁移工作正常(例如 dotnet ef database update)。

如果我想删除硬编码的连接字符串,我将面临以下问题:

我应该如何进行?

谢谢。

[编辑]

Startup.cs 中,我已经配置了连接字符串并且它工作正常(运行时):

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    //services.AddApplicationInsightsTelemetry(Configuration);

    string connString = ConfigurationExtensions.GetConnectionString(Configuration, "DefaultConnection");
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connString));

    services.AddMvc();
}

问题是 dotnet migrations 似乎需要数据库上下文中的无参数构造函数并实现 IDbContextFactory<>,我不知道如何注入配置。

尝试使用 ApplicationDbContext 的 IOptions<> 后编辑

我已经尝试了建议的解决方案,但我无法使其工作,因为 dotnet migration 将调用默认构造函数。

public class ApplicationDbContext : DbContext, IDbContextFactory<ApplicationDbContext>
{
    private IOptions<DefaultConnectionValue> ConnOptions;
    private string connectionString;

    public ApplicationDbContext()
    {
        Console.WriteLine("Default constructor was called");
    }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IOptions<DefaultConnectionValue> connOptions) : base(options)
    {
        ConnOptions = connOptions;
        connectionString = connOptions.Value.Value;

        Console.WriteLine($"Injected connection string = {connectionString}");
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }

    public ApplicationDbContext Create(DbContextFactoryOptions options)
    {
        var builder = new DbContextOptionsBuilder<ApplicationDbContext>();

        //string connString = ConfigurationExtensions.GetConnectionString(null, "DefaultConnection");
        builder.UseSqlServer(connectionString);
        return new ApplicationDbContext(builder.Options, ConnOptions);
    }

我遇到了同样的问题,我通过以下方式解决了它:

  1. 在服务集合中使用连接字符串注册选项
  2. 将选项注入 DBContext
  3. DBContext 无参数构造函数中的用户连接字符串

因此,您将拥有迁移所需的无参数构造函数。

注册配置设置的方法如下:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); //let's assume that here you have your connection string

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }

    public void ConfigureServices(IServiceCollection services)
    {
        // Adds services required for using options.
        services.AddOptions();

        // Register the IConfiguration instance which MyOptions binds against.
        services.Configure<MyOptions>(Configuration);

        ...
    }
}

然后您可以将其用作休假(这是控制器示例,但您可以对 DBContext 执行相同的操作):

public class HomeController : Controller
{
    private readonly MyOptions _optionsAccessor;

    public HomeController(IOptions<MyOptions> optionsAccessor)
    {
        //injection of your configuration object with connection string 
        _optionsAccessor = optionsAccessor.Value;
    }

    public IActionResult Index()
    {
        var option1 = _optionsAccessor.Option1;
        var option2 = _optionsAccessor.Option2;
        return Content($"option1 = {option1}, option2 = {option2}");
    }
}

有关配置设置用法的更多信息,请查看此处:Configuration

更新:

您也可以尝试不同的方法 - 读取 DBContext 构造函数内部的配置:

public class ApplicationDbContext : DbContext, IDbContextFactory<ApplicationDbContext>
{
    private string connectionString;

    public ApplicationDbContext()
    {
        var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); //let's assume that here you have your connection string
        var configuration = builder.Build();

        connectionString = ""; //FILL THE CONNECTION STRING FROM THE CONFIGURATION OBJECT
    }

    ...
}