如果迁移工具"dotnet ef database update"
在创建数据库之前运行我的应用程序BuildWebHost
,如何在使用迁移的同时构建需要访问我的数据库的服务?尝试配置需要数据库的服务会引发异常,因为数据库不存在并导致迁移命令失败。因此永远不会创建数据库。
我使用的是asp.net core 2和EF Core 2。
更具体地说,使用空白数据库运行"dotnet ef database update"
失败,并显示以下错误:
调用方法时遇到错误' BuildWebHost'在课堂上 '计划'。在没有应用服务提供商的情况下继续。错误: 无法打开数据库" MyDb"登录请求。登录失败。 用户' MYCOMPUTER \ MYNAME'。
登录失败
这是因为我已经构建了一个由我的" MyDb"支持的自定义配置提供程序。数据库(最终目标是使用自定义选项类绑定它)根据Microsoft Configuration Tutorial我的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();
并且AddMyOptionsConfig最终运行:
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);
在尝试访问数据库时抛出SQLException
,因为尚未创建数据库。
但是,如果我尝试使用dbContext.Database.EnsureCreated()
,则初始迁移将失败,因为表已存在。我想过尝试dbContext.Database.Migrate()
,但作为初学者,我担心可能会对生产环境产生意想不到的后果。因此,我更喜欢通过命令行工具控制迁移。
从根本上说,问题似乎是"dotnet ef database update"
运行应用程序启动 - BuildWebHost
- 在创建数据库之前,但BuildWebHost
中添加的自定义配置提供程序需要数据库已经存在
我该如何解决这个难题?
答案 0 :(得分:0)
从某种意义上说,您已创建了循环引用。在ASP.NET Core项目上运行迁移时,将初始化应用程序以实例化运行迁移所需的DbContext
。这是因为EF Core中的DbContext
现在需要注入一个DbContextOptions
实例,而不是EF中的旧方式,其中连接字符串名称(或实际完整)连接字符串)将直接在构造函数上定义。
通常,这可以正常工作,但是,正如您已经注意到的那样,因为应用程序初始化本身需要一个已经存在的数据库,所以在迁移之前无法运行它。因此,您有两种选择:
您可以尝试抽象需要现有数据库的部分。这可能就像将它包装在try-catch中并吞下异常或更复杂一样简单。由于迁移部分不需要此特定功能,因此可以安全地从该场景中的应用程序初始化中排除。
您可以将上下文和实体移动到类库中并实现IDesignTimeDbContextFactory
以满足构建要迁移的DbContext
的能力。然后,您将针对此类库而不是ASP.NET Core项目运行迁移。然后,回避了必须初始化应用程序以进行迁移的问题。
答案 1 :(得分:0)
BuildWebHost
(和Startup.Configure
)不应该用于应用程序启动逻辑。 ASP.NET团队的指导是使用Program.Main
代替。
答案 2 :(得分:0)
到目前为止,我的解决方案是将支持自定义配置提供程序的实体移动到单独的dbContext中。
现在可以在需要时通过MyDbOptionsContext.Database.EnsureCreated()
创建表而不影响迁移,因为它们基于主要上下文(MyDbContext
)。
选项表不再参与迁移,但因为它不太可能改变,所以应该没有问题。另一个缺点是需要(由于有两个上下文)来明确指定dotnet ef
命令行工具的上下文。