我在处理数据库连接字符串和迁移时遇到问题。我有2个项目:
DbContext
位于Domain项目中,因此这是我运行迁移的项目。迁移概念强制我在我的OnConfiguring
中实现DbContext
,并在其中指定数据库提供程序,例如:
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseSqlServer("<connection string>");
}
我的问题是我不想使用硬编码连接字符串,原因很明显,我不能使用ConfigurationManager从配置文件中读取它,因为配置文件在应用程序项目中。
我见过的所有示例都涉及对连接字符串进行硬编码或将其放入ASP.NET Core应用程序的设置文件中。
如果您不使用ASP.NET Core,或者我不知道,不希望将本地环境的数据库详细信息提交到源代码控制,则可以尝试使用临时环境变量。
首先,像这样实现IDesignTimeDbContextFactory
(请注意,IDbContextFactory
现已弃用):
public class AppContextFactory: IDesignTimeDbContextFactory<AppContext>
{
public AppContextFactory()
{
// A parameter-less constructor is required by the EF Core CLI tools.
}
public AppContext CreateDbContext(string[] args)
{
var connectionString = Environment.GetEnvironmentVariable("EFCORETOOLSDB");
if (string.IsNullOrEmpty(connectionString))
throw new InvalidOperationException("The connection string was not set " +
"in the 'EFCORETOOLSDB' environment variable.");
var options = new DbContextOptionsBuilder<AppContext>()
.UseSqlServer(connectionString)
.Options;
return new AppContext(options);
}
}
然后,您可以在调用Update-Database
或任何其他EF Core工具时包含环境变量:
$env:EFCORETOOLSDB = "Data Source=(local);Initial Catalog=ApplicationDb;Integrated Security=True"; Update-Database
我们遇到了同样的问题并且有一个解决方案。 :)
您必须实现IDbContextFactory<TContext>这样做时,您可以从appsettings.json中读取连接字符串。您也可以使用Add-Migration而不会出错,因为覆盖OnConfigure()
已经过时了。
示例实施:
public class DomainContextFactory : IDbContextFactory<DomainContext>
{
public string BasePath { get; protected set; }
public DomainContext Create()
{
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var basePath = AppContext.BaseDirectory;
return Create(basePath, environmentName);
}
public DomainContext Create(DbContextFactoryOptions options)
=> Create(options.ContentRootPath, options.EnvironmentName);
private DomainContext Create(string basePath, string environmentName)
{
BasePath = basePath;
var configuration = Configuration(basePath, environmentName);
var connectionString = ConnectionString(configuration.Build());
return Create(connectionString);
}
private DomainContext Create(string connectionString)
{
if (string.IsNullOrEmpty(connectionString))
{
throw new ArgumentException($"{nameof(connectionString)} is null or empty", nameof(connectionString));
}
var optionsBuilder = new DbContextOptionsBuilder<DomainContext>();
return Configure(connectionString, optionsBuilder);
}
protected virtual IConfigurationBuilder Configuration(string basePath, string environmentName)
{
var builder = new ConfigurationBuilder()
.SetBasePath(basePath)
.AddJsonFile("constr.json")
.AddJsonFile($"constr.{environmentName}.json", true)
.AddEnvironmentVariables();
return builder;
}
protected virtual string ConnectionString(IConfigurationRoot configuration)
{
string connectionString = configuration["ConnectionStrings:DefaultConnection"];
return connectionString;
}
protected virtual DomainContext Configure(string connectionString, DbContextOptionsBuilder<DomainContext> builder)
{
builder.UseSqlServer(connectionString, opt => opt.UseRowNumberForPaging());
DomainContext db = new DomainContext(builder.Options);
return db;
}
DomainContext IDbContextFactory<DomainContext>.Create(DbContextFactoryOptions options)
=> Create(options.ContentRootPath, options.EnvironmentName);
}
我们如何使用它:
public override IServiceResult<IList<Datei>> LoadAllData()
{
using (var db = this.DomainContextFactory.Create())
{
var files = db.Datei
.ToListAsync<Datei>();
return new ServiceResult<IList<Datei>>(files.Result, files.Result.Count);
}
}
示例配置
{
"ConnectionStrings": {
"DefaultConnection": "Put your connectionstring here"
}
}
这就是我如何做到这一点,没有太多额外的代码或疯狂。
项目结构:
我的DbContext是使用允许您注入DbContextOptions的构造函数设置的
asp net core project.data
public class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
}
在您的应用程序或Web应用程序中,您可以正常设置ConfigureServices
。
AspNetCoreProject.Web / Startup.cs / ConfigureServices()
services.AddDbContext<MyContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("connection"))
现在,迁移呢?好吧,我“欺骗”Visual Studio UI按预期工作。
AspNetCoreProject.Web
项目与Startup.cs
)是start up project。AspNetCoreProject.Data
类将其指向DbContext
或项目。add-migration init
然后update-database