首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架核心-在更改模型时,早期的数据迁移会中断

实体框架核心-在更改模型时,早期的数据迁移会中断
EN

Stack Overflow用户
提问于 2019-10-02 23:19:12
回答 2查看 1.1K关注 0票数 4

我们正在使用.NET Core、EF Core和Postgres启动一个新的应用程序--我们非常喜欢迁移:-)

然而,我发现了一个我无法解决的问题。在一些迁移中,我们使用DbContext加载记录,运行一些业务逻辑,并重新保存记录。我们还在web服务器启动时运行database.Context.Migrate(),因此它总是运行。

这一切都很好(到目前为止)。

不幸的是,它一直在工作,直到模型在以后的某个时候被更改。考虑以下迁移顺序:

  1. 创建CustomerOrderOrderLine模型。添加模式迁移以加载结构
  2. 业务规则会发生变化,因此我们需要根据某些业务逻辑在Order记录上设置一个值。我们创建一个数据迁移,在其中加载DbContext,运行代码,并运行SaveChangesAsync() 在这一点上,一切都好。
  3. 我们需要将带有新字段的模式迁移添加到Customer记录中。

在这里,一切都变坏了。如果数据库没有应用迁移2,则Migrate()命令错误,就像应用迁移2时一样,EF试图生成一个select语句,其中包含3中的新字段。

不过,我不知道问题到底在哪里:我们是否应该在迁移中使用DbContext (以及手动代码SQL语句)?我们是否应该明确地在每一次读取的记录上做预测,这样我们才能确切地知道自己在做什么?

还有别的吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-03 18:10:41

在您的示例中,1和3是架构迁移,2是数据迁移。

由于将根据代码中的当前模型(而不是数据库的当前状态)生成查询,因此有两个处理数据迁移的选项。

  1. 使用架构迁移按顺序执行数据迁移 在编写迁移时,使用像脱衣舞ADO.NET这样的工具来基于模式执行数据迁移。可以使用DbConnection从EF上下文中获取context.Database.GetDbConnection()对象。 优点:迁移代码永远不需要更改。 缺点:你得不到EF核心的任何好处
  2. 在架构迁移之后执行数据迁移 EF按照MigrationAttribute.Id字符串值的升序执行迁移。EF在调用dotnet ef migrations add xxx时基于时间戳生成此值。您可以更改此属性以确保在所有架构迁移之后运行数据迁移。为了可读性,也要更改文件名,这样它们就会按照应用的顺序排列。 优点:你可以得到EF核心的所有好处 缺点:如果模式将来发生变化,例如删除数据迁移中引用的列,则需要修改迁移。 示例MigrationAttribute.Id更改:
代码语言:javascript
复制
// change
[Migration("20191002171530_DataMigration")]
// to
[Migration("99999999000001_DataMigration")]
票数 5
EN

Stack Overflow用户

发布于 2021-09-27 13:02:25

我面临着一个类似的问题,并在这个问题上,我想我应该分享我的技术,以解决我的问题为后人。

在我的例子中,我们有一个模型Something,最初有一个字段/数据库列property,但是这个字段被废弃了,因为property最终存储在其他地方。我们编写了一个引用Something.property并将其移到新位置的数据迁移。

我们还想更新域模型以从property中删除Something。然而,这样做会破坏数据迁移中的类型转换。

我们必须有一个具有property的类型,以便允许数据迁移到打字机。但是,我们不能在域模型上使用property

解决方案是引入MigrationDbContext,它是标准DbContext的子类。MigrationDbContext公开了Somethings表的第二个投影,称为Somethings_WithProperty。这个投影是一个public DbSet<SomethingWithProperty>SomethingWithProperty类是具有当代属性的模型历史类型的记录;重要的是,我们只允许该类型出现在我们的Migrations文件夹中。SomethingWithProperty存储在Migrations/HistoricalModels中。

现在,我的数据迁移从依赖项注入中获得了一个MigrationDbContext,而不是一个DbContext。我可以将对dbcontext.Somethings的引用替换为dbcontext.Somethings_WithProperty,数据迁移可以进行类型检查。另一方面,我的域模型永远不会从MigrationDbContext获得,因此它能得到的唯一Something是来自Somethings DbSet,它正确地忽略了我们删除的property

几个注意事项;如果您的DbContext构造函数采用一般的DbContextOptions<MyDbContext>参数,那么为了满足依赖注入,您需要在MyDbContext上引入一个接受DbContextOptions<MigrationDbContext>参数的protected构造函数;子类可以在其构造函数中调用该构造函数。另外,MigrationDbContext最初会混淆两个投影映射到同一个表;在它的SetupSomethingsWithProperty方法中,您应该包括一个引用自然投影的外键,以消除混淆。

代码语言:javascript
复制
private static void SetupSomethingsWithProperty(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Something_WithProperty>(s =>
    {
        s.ToTable("Somethings");
        s.HasOne<Something>().WithOne().HasForeignKey<Something_WithProperty>(r => r.ID);
    });
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58210485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档