更新时间:2023-02-16 09:35:50
如果您正在寻找从 appsettings.json
文件初始化的自定义设置类中获取数据库连接字符串的解决方案 - 这就是方法你可以这样做.不幸的是,您无法通过 DI
将 IOptions
注入您的 IDesignTimeDbContextFactory
实现构造函数.
If you are looking for solution to get database connection string from your custom settings class initialized from appsettings.json
file - that is how you can do this. Unfortunatelly you can't inject IOptions
via DI
to your IDesignTimeDbContextFactory
implementation constructor.
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppContext>
{
public AppContext CreateDbContext(string[] args)
{
// IDesignTimeDbContextFactory is used usually when you execute EF Core commands like Add-Migration, Update-Database, and so on
// So it is usually your local development machine environment
var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
// Prepare configuration builder
var configuration = new ConfigurationBuilder()
.SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile($"appsettings.{envName}.json", optional: false)
.Build();
// Bind your custom settings class instance to values from appsettings.json
var settingsSection = configuration.GetSection("Settings");
var appSettings = new AppSettings();
settingsSection.Bind(appSettings);
// Create DB context with connection from your AppSettings
var optionsBuilder = new DbContextOptionsBuilder<AppContext>()
.UseMySql(appSettings.DefaultConnection);
return new AppContext(optionsBuilder.Options);
}
}
当然,在您的 AppSettings
类和 appsettings.json
中,您可以有更复杂的构建连接字符串的逻辑.例如,像这样:
Of course in your AppSettings
class and appsettings.json
you could have even more sophisticated logic of building the connection string. For instance, like this:
public class AppSettings
{
public bool UseInMemory { get; set; }
public string Server { get; set; }
public string Port { get; set; }
public string Database { get; set; }
public string User { get; set; }
public string Password { get; set; }
public string BuildConnectionString()
{
if(UseInMemory) return null;
// You can set environment variable name which stores your real value, or use as value if not configured as environment variable
var server = Environment.GetEnvironmentVariable(Host) ?? Host;
var port = Environment.GetEnvironmentVariable(Port) ?? Port;
var database = Environment.GetEnvironmentVariable(Database) ?? Database;
var user = Environment.GetEnvironmentVariable(User) ?? User;
var password = Environment.GetEnvironmentVariable(Password) ?? Password;
var connectionString = $"Server={server};Port={port};Database={database};Uid={user};Pwd={password}";
return connectionString;
}
}
仅存储在 appsettings.json
中的值:
{
"Settings": {
"UseInMemory": false,
"Server": "myserver",
"Port": "1234",
"Database": "mydatabase",
"User": "dbuser",
"Password": "dbpassw0rd"
}
}
密码和用户存储在环境变量中:
With password and user stored in environment variables:
{
"Settings": {
"UseInMemory": false,
"Server": "myserver",
"Port": "1234",
"Database": "mydatabase",
"User": "MY-DB-UID-ENV-VAR",
"Password": "MY-DB-PWD-ENV-VAR"
}
}
在这种情况下,您应该这样使用它:
In this case you should use it this way:
// Create DB context with connection from your AppSettings
var optionsBuilder = new DbContextOptionsBuilder<AppContext>();
if(appSettings.UseInMemory) {
optionsBuilder = appSettings.UseInMemory
? optionsBuilder.UseInMemoryDatabase("MyInMemoryDB")
: optionsBuilder.UseMySql(appSettings.BuildConnectionString());
return new AppContext(optionsBuilder.Options);