C# 是否有需要数据库的迁移和服务?
如果迁移工具C# 是否有需要数据库的迁移和服务?,c#,entity-framework,asp.net-core,entity-framework-core,C#,Entity Framework,Asp.net Core,Entity Framework Core,如果迁移工具“dotnet ef database update”在创建数据库之前运行我的应用程序BuildWebHost,那么我如何构建一个需要访问数据库的服务,同时也使用迁移?试图配置需要数据库的服务时引发异常,因为数据库不存在,并导致迁移命令失败。因此,永远不会创建数据库 我正在使用asp.NETCore2和EFCore2 更具体地说,使用空白数据库运行“dotnet ef database update”失败,错误如下: 在类上调用方法“BuildWebHost”时出错 “程序”。在没有
“dotnet ef database update”
在创建数据库之前运行我的应用程序BuildWebHost
,那么我如何构建一个需要访问数据库的服务,同时也使用迁移?试图配置需要数据库的服务时引发异常,因为数据库不存在,并导致迁移命令失败。因此,永远不会创建数据库
我正在使用asp.NETCore2和EFCore2
更具体地说,使用空白数据库运行“dotnet ef database update”
失败,错误如下:
在类上调用方法“BuildWebHost”时出错
“程序”。在没有应用程序服务提供商的情况下继续。错误:
无法打开登录请求的数据库“MyDb”。登录失败。
用户“MYCOMPUTER\MYNAME”登录失败
之所以会出现这种情况,是因为我构建了一个由我的“MyDb”数据库支持的自定义配置提供程序(最终目标是使用自定义选项类绑定到该数据库),my program.cs如下所示:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((builderContext, config) =>
{
var tmpconfig = config.Build();
config.AddMyOptionsConfig(options => options.UseSqlServer(tmpconfig.GetConnectionString("My_Database")));
})
.UseStartup<Startup>()
.Build();
公共静态IWebHost BuildWebHost(字符串[]args)=>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((builderContext,config)=>
{
var tmpconfig=config.Build();
config.addMyOptionConfig(options=>options.UseSqlServer(tmpconfig.GetConnectionString(“My_数据库”));
})
.UseStartup()
.Build();
AddMyOptionConfig最终会运行:
public class EFConfigProvider : ConfigurationProvider
{
[...]
// Load config data from EF DB.
public override void Load()
{
var builder = new DbContextOptionsBuilder<MyDbContext>();
OptionsAction(builder);
using (var dbContext = new MyDbContext(builder.Options))
{
// dbContext.Database.EnsureCreated(); // will cause first migration to fail
Data = !dbContext.ConfigurationValue.Any() // throws exception
? CreateAndSaveDefaultValues(dbContext)
: dbContext.ConfigurationValue.ToDictionary(c => c.Id, c => c.Value);
公共类EFConfigProvider:ConfigurationProvider
{
[...]
//从EF DB加载配置数据。
公共覆盖无效负载()
{
var builder=new DbContextOptionsBuilder();
选择行动(承建商);
使用(var dbContext=newmydbcontext(builder.Options))
{
//dbContext.Database.EnsureCreated();//将导致第一次迁移失败
Data=!dbContext.ConfigurationValue.Any()//引发异常
?CreateAndSaveDefaultValues(dbContext)
:dbContext.ConfigurationValue.ToDictionary(c=>c.Id,c=>c.Value);
它在试图访问数据库时抛出一个SQLException
,因为数据库尚未创建
但是,如果我尝试使用dbContext.Database.EnsureCreated()
,则初始迁移会失败,因为表已经存在。我想尝试dbContext.Database.Migrate()
相反,作为初学者,我担心可能会对生产环境造成意外后果。因此,我更希望通过命令行工具控制迁移
基本上,问题似乎是“dotnet ef database update”
在创建数据库之前运行应用程序启动-BuildWebHost
,但是BuildWebHost
中添加的自定义配置提供程序需要数据库已经存在
如何解决这个难题?从某种意义上说,您已经创建了一个循环引用。在ASP.NET核心项目上运行迁移时,应用程序被初始化为实例化运行迁移所需的
DbContext
。这是因为EF核心中的DbContext
现在需要DbContextOptions
要注入的实例,这与在EF中执行操作的旧方法不同,在EF中,连接字符串名称(或实际的完整连接字符串)将直接在构造函数上定义
通常情况下,这会很好地工作,但是,正如您所注意到的,因为应用程序初始化本身需要一个已经存在的数据库,所以在迁移之前无法运行它。因此,您有两个选项:
DbContext
的能力。然后,您可以对该类库而不是ASP.NET核心项目运行迁移。这样就避免了必须初始化应用程序才能执行迁移的问题迁移BuildWebHost
(和Startup.Configure
)不应用于应用程序启动逻辑。ASP.NET团队的指导是使用Program.Main
。到目前为止,我的解决方案是将支持自定义配置提供程序的实体移动到单独的dbContext中
现在,可以在需要时通过mydboptioncontext.Database.EnsureCreated()
创建表,而不影响迁移,因为它们基于主上下文(MyDbContext
)
选项表不再参与迁移,但由于不太可能更改,因此不应该出现问题。另一个缺点是需要(由于有两个上下文)要显式指定
dotnet ef
命令行工具的上下文,请执行以下操作。我正在尝试将自定义选项类添加为服务。如何在BuildWebHost
(和Startup.ConfigureServices
之外添加服务?我看不出有什么方法可以做到这一点。你能添加服务,但让它变懒,这样它就不会运行在设计时失败的代码吗?它是一个内置的dotnet核心服务services.Configure(Configuration);
,但我很快就看到了。我怀疑数据库在IConfigurationBuilder.Build()之后就被击中了
被调用,我假设这发生在启动之前。我喜欢wa