Visual studio 2017 ef核心迁移可以';不要使用秘密管理器
当我创建.net核心web应用程序时,我在测试期间使用secret manager。我通常能够创建一个新的web项目(mvc和web api),右键单击该项目并选择“管理用户机密”。这将打开一个json文件,我在其中添加机密。然后我在startup.cs中使用它,如下所示:Visual studio 2017 ef核心迁移可以';不要使用秘密管理器,visual-studio-2017,asp.net-core-2.0,entity-framework-core-migrations,secret-manager,Visual Studio 2017,Asp.net Core 2.0,Entity Framework Core Migrations,Secret Manager,当我创建.net核心web应用程序时,我在测试期间使用secret manager。我通常能够创建一个新的web项目(mvc和web api),右键单击该项目并选择“管理用户机密”。这将打开一个json文件,我在其中添加机密。然后我在startup.cs中使用它,如下所示: services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(Configuration["connectionSt
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(Configuration["connectionString"]));
后来:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" />
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
是否需要添加任何内容,以便迁移可以访问连接字符串
更新
我在上下文类中只有一个构造函数:
public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options)
{
}
public ApplicationDBContext(DbContextOptions选项):基本(选项)
{
}
我目前也遇到了这个问题。我已经想出了一个解决办法,现在工作,但人们可能会考虑混乱最好。
我创建了一个配置类,该类在请求时提供配置接口:
公共静态类配置
{
公共静态IConfiguration GetConfiguration()
{
返回新的ConfigurationBuilder()
.AddJsonFile(“appsettings.json”,true,true)
.AddUserSecrets()
.AddenEnvironmentVariables()
.Build();
}
}
在迁移过程中,您可以获取配置文件并访问其用户机密,如下所示:
protected override void Up(MigrationBuilder MigrationBuilder)
{
var conf=Configuration.GetConfiguration();
var secret=conf[“secret”];
}
我已经测试过使用这些用户机密创建一个SQL脚本,它可以正常工作(显然,您不想让脚本继续运行,因为它会暴露实际的机密)
更新
也可以在BuildWebHost
方法中将上述配置设置为Program.cs类:
var config=new ConfigurationBuilder().AddUserSecrets().Build();
返回WebHost.CreateDefaultBuilder(args).UseConfiguration(config)…Build()
或者在启动构造函数中,如果使用
更新2(说明)
事实证明,这个问题是因为迁移脚本在环境设置为“生产”的情况下运行。机密管理器被预先设置为仅在“开发”环境中工作(这是有充分理由的)。.AddUserSecrets()
函数只是为所有环境添加机密
为了确保不将此设置为生产服务器,我注意到有两种解决方案,这里建议使用其中一种:
在运行前设置env:ASPNETCORE_环境以指定ASP.NET核心环境
此解决方案意味着以后无需在计算机上创建的每个项目上设置.AddUserSecrets()
。但是,如果您碰巧在其他计算机上共享此项目,则需要在每台计算机上配置此项目
第二种解决方案是仅在调试版本上设置.AddUserSecrets()
,如下所示:
返回新的ConfigurationBuilder()
.AddJsonFile(“appsettings.json”,true,true)
#如果调试
.AddUserSecrets()
#恩迪夫
.AddenEnvironmentVariables()
.Build();
其他信息
配置接口可以传递给其构造函数中的控制器,即
专用只读IConfiguration\u配置;
公共测试控制器(IConfiguration配置)
{
_配置=配置;
}
因此,可以通过访问\u配置[“secret”]
在该控制器中访问任何机密和应用程序设置
但是,如果您想从(例如)存在于Web应用程序本身之外的迁移文件中访问应用程序机密,则需要遵循原始答案,因为(据我所知)没有其他方法可以轻松访问这些机密(我能想到的一个用例是在数据库中植入管理员和主密码)。要在NetCore中使用带有用户机密的迁移,我们还可以设置一个类(SqlContextFactory)使用指定的配置生成器创建它自己的SqlContext实例。这样,我们不必在程序或启动类中创建某种解决方法。在下面的示例中,
SqlContext
是DbContext/IdentityDbContext
的一个实现
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
public class SqlContextFactory : IDesignTimeDbContextFactory<SqlContext>
{
public SqlContext CreateDbContext(string[] args)
{
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddUserSecrets<Startup>()
.AddEnvironmentVariables()
.Build();
var builder = new DbContextOptionsBuilder<SqlContext>();
builder.UseSqlServer(config.GetConnectionString("DefaultConnection"));
return new SqlContext(builder.Options);
}
}
使用Microsoft.EntityFrameworkCore;
使用Microsoft.EntityFrameworkCore.Design;
使用Microsoft.Extensions.Configuration;
公共类SqlContextFactory:IDesignTimeDbContextFactory
{
公共SqlContext CreateDbContext(字符串[]args)
{
var config=new ConfigurationBuilder()
.AddJsonFile(“appsettings.json”,可选:false)
.AddUserSecrets()
.AddenEnvironmentVariables()
.Build();
var builder=new DbContextOptionsBuilder();
builder.UseSqlServer(config.GetConnectionString(“DefaultConnection”);
返回新的SqlContext(builder.Options);
}
}
如果我们在单独的类库中使用DbContext并使用DesignTimeFactory,那么使用.AddUserSecrets()
的方法将成为循环引用
清洁的方法是:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
#if DEBUG
.AddJsonFile(@Directory.GetCurrentDirectory() + "{project path}/appsettings.Development.json", optional: true, reloadOnChange: true)
#else
.AddJsonFile(@Directory.GetCurrentDirectory() + "{startup project path}/appsettings.json", optional: true, reloadOnChange: true)
#endif
.AddEnvironmentVariables()
.Build();
var connectionString = configuration.GetConnectionString("DefaultConnection");
//Console.WriteLine(connectionString);
var builder = new DbContextOptionsBuilder<AppDbContext>();
Console.WriteLine(connectionString);
builder.UseSqlServer(connectionString);
return new AppDbContext(builder.Options);
}
}
公共类DesignTimeDbContextFactory:IDesignTimeDbContextFactory
{
公共AppDbContext CreateDbContext(字符串[]args)
{
var configuration=new ConfigurationBuilder()
.SetBasePath(目录.GetCurrentDirectory())
#如果调试
.AddJsonFile(@Directory.GetCurrentDirectory()+“{project path}/appsettings.Development.json”,可选:true,重载更改:true)
#否则
.AddJsonFile(@Directory.GetCurrentDirectory()+“{startup project path}/appsettings.json”,可选:true,重载更改:true)
#恩迪夫
.AddenEnvironmentVariables()
.Build();
var connectionString=configuration.GetConnectionString(“DefaultConnection”);
//Console.WriteLine(连接字符串
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
#if DEBUG
.AddJsonFile(@Directory.GetCurrentDirectory() + "{project path}/appsettings.Development.json", optional: true, reloadOnChange: true)
#else
.AddJsonFile(@Directory.GetCurrentDirectory() + "{startup project path}/appsettings.json", optional: true, reloadOnChange: true)
#endif
.AddEnvironmentVariables()
.Build();
var connectionString = configuration.GetConnectionString("DefaultConnection");
//Console.WriteLine(connectionString);
var builder = new DbContextOptionsBuilder<AppDbContext>();
Console.WriteLine(connectionString);
builder.UseSqlServer(connectionString);
return new AppDbContext(builder.Options);
}
}