我遇到了与迁移一起处理数据库连接字符串的问题。 我有2个项目:
DbContext
位于Domain项目中,因此这是我运行迁移的项目。
迁移概念强制我在OnConfiguring
中实现DbContext
,并在其中指定数据库提供者,例如:
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseSqlServer("<connection string>");
}
我的问题是我不想使用硬编码连接字符串,原因显而易见,我不能使用ConfigurationManager从配置文件中读取它,因为配置文件在应用程序项目中。
答案 0 :(得分:4)
我看到的所有示例都涉及对连接字符串进行硬编码或将其放入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
答案 1 :(得分:1)
我们遇到了同样的问题并且有一个解决方案。 :)
你必须实施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"
}
}
答案 2 :(得分:1)
这就是我的方法,没有很多额外的代码或疯狂。
项目结构:
AspNetCoreProject.Web
AspNetCoreProject.Data <-DbContext在这里
我的DbContext是使用构造函数设置的,该构造函数允许您注入DbContextOptions
AspNetCoreProject.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
的{{1}}项目是start up project。
第二,打开您的Nuget软件包管理器控制台。在Nuget PM>控制台的顶部,有一个“设置默认项目” 的下拉菜单,将其指向您的Startup.cs
或具有AspNetCoreProject.Data
类的项目。
正常运行migration commands。 DbContext
,然后add-migration init
答案 3 :(得分:1)
我在Windows环境变量MsSql.ConnectionString
中配置了以下配置时使用了OnConfiguring,并且开始进行ef迁移创建的命令开始起作用:dotnet ef migrations add InitialCreate
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionString = Environment.GetEnvironmentVariable("MsSql.ConnectionString");
if(string.IsNullOrEmpty(connectionString))
throw new ConfigurationErrorsException("Sql server connection string configuration required");
if (!optionsBuilder.IsConfigured)
{
optionsBuilder
.UseSqlServer(connectionString)
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}
}
要配置环境变量:
Win + R
热键组合打开Run
命令窗口systempropertiesadvanced
,然后按Enter Advanced
标签上,点击Environment Variables
New...
按钮Variable name
字段中,输入MsSql.ConnectionString
Variable value
字段中输入您的连接字符串值确保在添加新变量之后并且在运行dotnet ef
相关命令之前重新启动控制台(以及启动控制台的任何程序)
答案 4 :(得分:0)
我在控制台应用程序中使用了DBContext,并且正在使用带有很少参数(例如连接字符串等)的ctor,因为EF Core Migrations使用的默认参数少了ctor,因此没有填充连接字符串迁移失败。
只需添加代码即可在默认ctor中从ConfigurationBuilder获取连接字符串,以通过此操作。
仅在与控制台应用程序和EF Core一起玩,所以这对我来说现在可行。
答案 5 :(得分:0)
假设您的 DbContext 类具有接受 DbContextOptions 类型参数的构造函数,则 dotnet ef 命令对这种情况具有本机支持 - 无需更改代码或额外配置。创建和运行迁移时只需使用“--startup-project”和“--project”参数即可。
例如,假设您有一个“应用程序”项目和一个名为“域”的单独项目,其中实现了 DbContext。
首先在Application项目启动类中的服务提供者中添加DbContext。然后运行以下命令:
dotnet ef database update --startup-project Application --project Domain