如何解决EntityFramework Core 自动迁移 是否需要调用 Migrate()?检测是否需要迁移澄清迁移 vs EnsureCreated
在我的项目中,我有 2 个数据库:一个是我的自定义数据库,另一个是 ApplicationDbContext
给我的 Microsoft Identity
。
public void Configure(IApplicationBuilder app,IWebHostEnvironment env,ApplicationDbContext db,MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
db.Database.Migrate();
dbPSC.Database.EnsureCreated();
dbPSC.Database.Migrate();
}
- 除了第一次之外,每次应用程序启动时
ApplicationDbContext
的迁移都会引发错误 - 我的上下文的迁移看起来不错
最好的做法是什么?是否需要调用 ApplicationDbContext
的迁移?
更新
我已删除 Migration
文件夹。然后,将 Startup.cs
更改为
public void Configure(IApplicationBuilder app,MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
dbPSC.Database.EnsureCreated();
}
但是当应用程序启动时,它根本不创建任何表。 AuditDbContext
是因为我使用 Audit.net
public class MyContext : AuditDbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options) { }
public DbSet<Message> Messages { get; set; }
public DbSet<AuditMessage> Audit_Messages { get; set; }
#region Common Tables
public DbSet<Country> Countries { get; set; }
public DbSet<AuditCountry> Audit_Countries { get; set; }
#endregion
#region Seed
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Seed();
}
#endregion
}
更新 #2
我尝试了另一种解决方案,但它不起作用。解决方法是像下面的代码一样使用RelationalDatabaseCreator
public void Configure(IApplicationBuilder app,MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
dbPSC.Database.EnsureCreated();
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();
}
作为 Migrate()
,应用程序第一次运行时会创建表,但第二次会引发错误,因为这些表已存在于数据库中。
解决方法
问题很可能是您调用了 EnsureCreated()
。
来自docs:
请注意,此 API 不使用迁移来创建数据库。 此外,创建的数据库无法在以后使用迁移进行更新。如果您的目标是关系数据库并使用迁移,则可以使用 DbContext.Database.Migrate() 方法来确保数据库是已创建并应用所有迁移。
所以,调用 Migrate()
就足够了。但我不怪你,因为 EnsureCreated()
绝对是一个误导性的方法名称。它做了很多事情,因为它还创建了甚至不基于迁移,而是基于实体的当前状态的数据库架构。
但是如果您不想对 Identity 上下文使用迁移(因为您不以任何方式扩展这些实体),则相反:您不需要调用Migrate()
,调用 EnsureCreated()
就足以确保第一次创建架构。
是否需要调用 Migrate()
?
至于什么是最佳实践:一些开发人员根本不喜欢从代码中调用 Migrate()
,因为他们认为像这样的 DB 模式操作应该受到更多控制(我相信你知道你可以也从 CLI 执行 db update)。我猜这取决于您的要求。
关于为身份表使用单独的数据库的这种特定情况:它们很可能永远不会改变,尤其是它们不会自己创建迁移。所以我会说调用 Migrate()
是不必要的,除了它可以创建和迁移不存在的数据库的事实(因此保留这个原因可能很有用;如果你是开始使用该上下文的迁移)。
检测是否需要迁移
您可以使用 context.Database.GetPendingMigrationsAsync()
来检查是否需要迁移。它是如何完成的,DB 有一个 EFMigrationsHistory
表,用于存储已应用迁移的 Id,可以将其与您的解决方案中的迁移文件进行比较。
但我认为大多数开发人员不会将其称为 GetPendingMigrationsAsync()
(或同步版本,就此而言),因为您可以直接调用 Migrate()
,如果数据库已经更新,则无害完成了。
澄清迁移 vs EnsureCreated
我不确定您与 EF 合作了多少,所以这很明显。但是当您已经使用例如创建迁移时使用 Migrate()
dotnet ef migrations add <migrationname>
,这是一种使用代码优先的方法逐步改变数据库架构的方法。
但是如果您根本不使用迁移,那么您将拥有一个非常简单的架构,不需要随着迁移而增量更改,并且您只想确保数据库存在一个架构,然后使用只使用 EnsureCreated()
,不要使用 Migrate()
。
问题是,如果您碰巧更改了实体,EnsureCreated()
将不会更新数据库;如果数据库已经存在,它什么都不做。因此,您必须先调用 EnsureDeleted()
,然后调用 EnsureCreated()
才能实现无需迁移的最新数据库架构。这显然涉及丢失所有数据。这就是迁移有用的原因。 EnsureCreated()
主要用于例如集成测试。
顺便说一句,您可以为自己的表和身份使用相同的数据库上下文;我敢说这是与 EF 合作的“正常”方式。当然,我想你可能有你分开的具体原因。
,您不需要同时使用 db.Database.EnsureCreated();
和 db.Database.Migrate();
当您的应用程序中没有启用迁移时,您需要使用 db.Database.EnsureCreated();
。如果您启用了迁移,那么只使用 db.Database.Migrate();
就足够了。
但是如果您不启用迁移,那么在每次更改时您都必须重新创建您的数据库。因为“EnsureCreated”只验证数据库是否已经存在。所以最好启用迁移。
因此,如果您不想更改 ApplicationDbContext 中的任何内容以便可以使用 db.Database.EnsureCreated();
但如果您想更改某些内容或者您可能想在 AspNetUsers 等中添加更多字段,那么您应该启用迁移并使用db.Database.Migrate();
顺便说一句,如果需要,您也可以在 ApplicationDbContext 中添加自定义表。
,根据你们发给我的回复,我的解决方案是使用迁移。在 Startup.cs
中,我添加了这些代码行(dbPSC 是 DbContext
)
dbPSC.Database.EnsureCreated();
if (dbPSC.Database.GetPendingMigrations().Count() > 0)
dbPSC.Database.Migrate();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。