起初,我们使用了自动迁移和基于代码的迁移的混合方式。这根本行不通,所以我们决定禁用自动迁移,并只允许基于代码的迁移。我应该补充一点,我们重新开始使用一个干净的数据库,没有来自所有自动迁移的“损坏”的_MigrationsHistory。
所以现在的工作流程是:
1. 开发人员更改他的数据模型 2. 使用add-migration 并将其应用到他的数据库中,使用update-database。 3. 将数据模型更改和迁移提交到Git中。 4. 另一个开发人员拉取,接收更改,并将其应用到他的数据库中。
到目前为止,这个方法运作良好。然而,今天之前通常只有我制作迁移,其他人应用它们。但今天有三个开发人员的迁移。我刚刚拉取了这些迁移,做了一个update-database,一切顺利。
我自己的数据模型也进行了更改,因此在执行
update-database
之后,它警告我仍然不是最新的,所以我运行了add-migration <my migration>
。但是当它生成迁移时,它给我展示了我已经应用到数据库中的所有迁移更改。因此:它尝试删除已经被删除的列,尝试创建已经存在的表等等。这是怎么回事呢?我的假设是EF只会检查_MigrationsHistory
表,并找出哪些迁移尚未在该表中出现,并按照名称中的时间戳顺序逐个应用它们。但显然不是这样,因为即使我撤销了自己的更改并且具有清洁的环境,它仍然抱怨我的数据库与模型不同步。但是我刚刚拉取了这些更改并将它们应用到了我的数据库中。它已经同步了。我也可以在_MigrationsHistory
表中看到我刚刚应用的迁移。
List<X>
,其中X是一对多关系中的多。这不会导致数据库更改,因为X已经有一个指向Y的外键)。这可能是原因吗?如果是这样,那真的很脆弱,因为没有办法为此添加迁移,因为没有数据库更改,我也不确定如何解决这个问题。我不确定该怎么处理这个问题,因为我当然可以编辑它生成的内容并删除已应用于我的数据库的所有内容。但接下来呢?我提交它,然后其他开发人员收到相同的消息,即他的数据库仍未更新,即使应用了我的新更改,他们自己进行了脚手架式的更改,得到了相同的无意义的脚手架,编辑它,提交它,然后下一个开发人员就会遇到同样的问题。这变成了一个恶性循环,类似于我们使用自动迁移时遇到的问题,我认为我们通过切换到仅基于代码解决了这个问题。我现在无法信任它执行正确的操作,像这样工作真是一场噩梦。
以下是翻译的结果:
我尝试了添加我从同事那里拉取的迁移,每次只添加一个,使用update-database -t:201211091112102_<migrationname>
,但都没有成功。它仍然给我错误的脚手架。
那么我们做错了什么呢?或者EF根本不适合这样的协作方式?
更新
我创建了一个可重现的测试用例,但为了模拟这种多用户/多数据库的情况,需要进行一些冗长的操作。
https://github.com/JulianR/EfMigrationsTest/
当您拥有上述项目时,按照以下步骤进行复制(这些步骤也在代码中):- add-migration Init(添加迁移项Init)
- update-database (对于数据库'TestDb'进行更新)
- 更改连接字符串以指向TestDb1(Change connection string to point to TestDb1)
- 在TestDb1上进行update-database更新
- 取消注释类Test上的属性Foo(Uncomment property Foo on class Test)
- 添加迁移项M1以将属性Foo添加到TestDb1中
- 再次注释掉Test.Foo
- 更改连接字符串以指向TestDb2(Change connection string to point to TestDb2)
- 从项目中排除迁移项M1,以便不将其应用于TestDb2中(Exclude migration M1 from project so it doesn't get applied to TestDb2)
- 取消注释类Test上的属性Bar
- update-database以将Init迁移应用于TestDb2(update-database to apply Init migration to TestDb2)
- 添加迁移项M2以将属性Bar添加到TestDb2中
- 再次更改连接字符串以指向原始的TestDb
- 再次将迁移项M1包含到项目中
- 取消注释类Test上的属性Foo
- 取消注释类Test上的属性SomeInt
- update-database更新数据库
- 添加迁移项M3,并因为迁移项M3尝试添加已由迁移项M1添加到数据库TestDb中的列Foo而产生错误
update-database
来应用用户2和3的更改。然后他生成了自己的迁移,但错误地将用户2或3的更改添加到了生成的迁移中,导致在应用于用户1的数据库时出现错误。