协作环境中实体框架中的迁移 [英] Migrations in Entity Framework in a collaborative environment

查看:21
本文介绍了协作环境中实体框架中的迁移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有多个开发人员正在开发一个使用 Entity Framework 5.0 的项目.每个开发人员都使用自己的本地 SQL 2012 数据库,因此他可以在不妨碍他人的情况下进行开发和测试.

We have multiple developers working on a project that uses Entity Framework 5.0. Every developer uses his own local SQL 2012 database so he can develop and test without impeding others.

起初,我们混合使用了自动迁移和基于代码的迁移.这根本不起作用,所以我们决定禁用自动迁移并只允许基于代码的迁移.我应该补充一点,我们从一个干净的数据库重新开始,没有来自所有自动迁移的损坏"_MigrationsHistory.

At first, we used a hybrid of automatic migrations and code-based migrations. That didn't work well at all so we decided to disable automatic migrations and to only allow code-based. I should add that we started again with a clean database without a 'corrupted' _MigrationsHistory from all the automatic migrations.

所以现在的工作流程是:

So now the workflow is:

  1. 开发人员更改了他的数据模型
  2. add-migration <Name> 并使用 update-database 将其应用到他的数据库.
  3. 检查数据模型更改并迁移到 Git.
  4. 另一位开发人员提取、接收更改并将其应用到他的数据库.
  1. Developer changes his datamodel
  2. Does add-migration <Name> and applies it to his database with update-database.
  3. Checks in the datamodel change and the migration into Git.
  4. Another developer pulls, receives the changes and applies it to his database.

到目前为止,这运作良好.然而在今天之前,通常只有我进行迁移,其他人应用它们.但是今天有来自三个开发人员的迁移.我刚刚取消了这些迁移,做了一个 update-database 一切正常.

So far, this worked well. However before today it was usually just me who made the migrations and the others applied them. But today there were migrations from three developers. I just pulled those migrations, did an update-database which went fine.

我也对我自己的数据模型进行了更改,但是在 update-database 的末尾它给了我一个警告,我仍然不是最新的所以我做了 add-migration <我的迁移>.但是,当它为迁移搭建脚手架时,它给了我已经应用到数据库的所有迁移的更改.所以:它试图删除已经被删除的列,试图创建一个已经存在的表,等等.

I also had a change to my own datamodel however so at the end of the update-database it gave me a warning that I still wasn't up to date so I did add-migration <my migration>. However when it scaffolded the migration, it gave me the changes of all the migrations I had already applied to the database. So: it tried to drop columns that had already been dropped, tried to create a table that already existed, etc.

怎么可能?我的假设是 EF 只会检查 _MigrationsHistory 表并找出表中尚不存在哪些迁移,并按名称中的时间戳顺序逐一应用这些迁移.但显然不是,因为即使我撤消自己的更改并且我有一个干净的环境,它仍然会抱怨我的数据库与模型不同步.但我只是提取了这些更改并将它们应用到我的数据库中.它同步的.我也可以在 _MigrationsHistory 表中看到我刚刚应用的迁移.

How can that be? My assumption was that EF would just check the _MigrationsHistory table and find out which migrations weren't present in the table yet and apply those one by one ordered by the timestamp that's part of the name. But apparently not, because even when I undo my own changes and I have a clean environment it still complains my database isn't in sync with the model. But I just pulled those changes and applied them to my database. It is in sync. I can see the migrations that I just applied in the _MigrationsHistory table too.

我唯一能想到的是我向数据模型添加了一个不会导致数据库更改的属性(我向数据模型 Y 添加了一个 List<X> ,其中 X 是许多在一对多的关系中.这不会导致数据库更改,因为 X 已经有 Y 的外键).会是这样吗?如果是这样,那真的很脆弱,因为没有办法为此添加迁移,因为没有数据库更改,我也不知道如何解决这个问题.

The only thing I can think of is that I added a property to a datamodel that wouldn't result in a database change (I added a List<X> to datamodel Y where X is the many in the one-to-many relationship. This wouldn't result in a database change as X already had a foreign key to Y). Could that be it? If so, that's really fragile because there's no way to add a migration for that since there's no database change and I'm not sure how to fix this either.

我不知道如何处理这个问题,因为我当然可以编辑它所搭建的内容并删除已应用于我的数据库的所有内容.但是然后呢?我签入它,然后其他一些开发人员收到相同的消息,即使在应用我的新更改后,他的数据库也不是最新的,搭建他自己的更改,获得相同的废话脚手架,编辑它,签入,然后 下一个 开发者得到它.它变成了一个恶性循环,与我们使用自动迁移时的情况类似,我认为我们已经通过切换到仅基于代码的方式解决了这个问题.我现在不能相信它会做正确的事,像这样工作简直是一场噩梦.

I'm not sure how to deal with this, because I can of course just edit what it scaffolded and remove everything that has already been applied to my database. But then what? I check it in and then some other developer gets the same message that his database isn't up to date even after applying my new changes, scaffolds his own changes, gets the same nonsense scaffolding, edits it, checks it in and then the next developer gets it. It becomes a vicious circle and a similar one to what we had when we used automatic migrations and I thought we had fixed that by switching to code-based only. I can't trust it right now to do the right thing and it's a nightmare to work with like this.

我还尝试使用 update-database -t:201211091112102_ 逐一添加我从同事那里提取的迁移,但无济于事.它仍然给了我错误的脚手架.

What I also tried is adding the migrations I pulled from my coworkers one by one with update-database -t:201211091112102_<migrationname> but to no avail. It still gives me the erroneous scaffold.

那么我们在这里做错了什么,或者 EF 根本不是为这样的协作而构建的?

So what did we do wrong here, or is EF simply not built for collaboration like this?

更新

我创建了一个可重现的测试用例,但为了模拟这种多用户/多数据库场景,这有点冗长.

I created a reproducible test case, it's a bit of a lengthy dance though in order to simulate this multi user/multi database scenario.

https://github.com/JulianR/EfMigrationsTest/

当您拥有上述项目时重现的步骤(这些步骤也存在于代码中):

Steps to reproduce when you have the above project (these steps are also present in the code):

  1. 添加迁移初始化
  2. 更新数据库(在数据库TestDb"上)
  3. 更改连接字符串以指向 TestDb1
  4. 在 TestDb1 上更新数据库
  5. 取消注释类 Test 上的属性 Foo
  6. 添加迁移 M1 以将属性 Foo 添加到 TestDb1
  7. 再次注释掉 Test.Foo
  8. 更改连接字符串以指向 TestDb2
  9. 从项目中排除迁移 M1,使其不会应用于 TestDb2
  10. 取消注释类 Test 上的属性 Bar
  11. 更新数据库以将 Init 迁移应用到 TestDb2
  12. 添加迁移 M2 以将属性 Bar 添加到 TestDb2
  13. 更改连接字符串以再次指向原始 TestDb
  14. 再次将迁移 M1 包含到项目中
  15. 取消注释类 Test 上的属性 Foo
  16. 取消注释类 Test 上的 SomeInt 属性
  17. 更新数据库
  18. 添加迁移 M3
  19. update-database,因为 M3 试图将 Foo 列添加到数据库 TestDb 中,而该列已经由迁移 M1 添加.

上面是模拟三个用户,其中用户1初始化他的数据库,另外两个使用他的初始化来创建他们的数据库.然后用户 2 和用户 3 都对数据模型进行了自己的更改,并将其与应用更改所需的迁移一起添加到源代码管理中.然后用户 1 拉取用户 2 和 3 的更改,而用户 1 自己也对数据库进行了更改.然后用户 1 调用 update-database 来应用用户 2 和 3 的更改.然后他搭建自己的迁移,然后错误地将用户 2 或 3 的更改添加到脚手架迁移中,从而导致错误应用于用户 1 的数据库.

The above is to simulate three users, where user 1 inits his database, the other two use his initialization to create their database as well. Then user 2 and user 3 both make their own change to the datamodel and add it to source control together with the migrations needed to apply the changes. Then user 1 pulls the changes of user 2 and 3 while user 1 has also made a change to the database himself. Then user 1 calls update-database to apply the changes of user 2 and 3. He then scaffolds his own migration which then erroneously adds a change from user 2 or 3 to the scaffolded migration which causes an error when applied to user 1's database.

推荐答案

您需要像处理代码冲突一样手动解决迁移冲突.如果您更新并且有新的迁移,则需要确保上次迁移背后的元数据与当前模型匹配.要更新迁移的元数据,请为其重新发出 Add-Migration 命令.

You need to manually resolve migration conflicts just like you would code conflicts. If you update and there are new migrations, you need to ensure that the metadata behind the last migration matches the current model. To update the metadata of the migration, re-issue the Add-Migration command for it.

例如,在您的场景中的第 17 步(更新数据库)之前,您应该发出以下命令

For example, before step 17 (Update-Database) in your scenario, you should issue the following command

Add-Migration M2

这将更新元数据以使其与您当前的模型同步.现在,当您尝试添加 M3 时,它应该是空白的,因为您还没有进行任何进一步的模型更改.

This will update the metadata to bring it in sync with your current model. Now when you try and add M3, it should be blank since you have not made any further model changes.

这篇关于协作环境中实体框架中的迁移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆