我们有多个开发人员正在开发一个使用 Entity Framework 5.0 的项目。每个开发人员都使用自己的本地 SQL 2012 数据库,这样他就可以在不妨碍其他人的情况下进行开发和测试。
起初,我们混合使用自动迁移和基于代码的迁移。这根本不起作用,因此我们决定禁用自动迁移并只允许基于代码的迁移。我应该补充一点,我们从一个干净的数据库重新开始,没有“损坏”_MigrationsHistory
来自所有自动迁移。
所以现在的工作流程是:
- 开发人员更改他的数据模型
- Does
add-migration <Name>
并将其应用到他的数据库中update-database
.
- 签入数据模型更改以及迁移到 Git 中。
- 另一位开发人员拉取、接收更改并将其应用到他的数据库中。
到目前为止,这效果很好。然而,在今天之前,通常只有我进行迁移,其他人应用它们。但今天有来自三个开发人员的迁移。我刚刚取消了这些迁移,做了一个update-database
一切顺利。
我也对我自己的数据模型进行了更改,但是在最后update-database
它给了我一个警告,我仍然没有更新,所以我做了add-migration <my migration>
。然而,当它构建迁移时,它给了我已经应用于数据库的所有迁移的更改。所以:它尝试删除已经删除的列,尝试创建一个已经存在的表,等等。
怎么可能?我的假设是 EF 只会检查_MigrationsHistory
表并找出表中尚不存在的迁移,并按名称中的时间戳顺序一一应用这些迁移。但显然不是,因为即使当我撤消自己的更改并且我有一个干净的环境时,它仍然抱怨我的数据库与模型不同步。但我只是提取了这些更改并将它们应用到我的数据库中。它is同步中。我可以看到我刚刚应用的迁移_MigrationsHistory
表也。
我唯一能想到的是,我向数据模型添加了一个不会导致数据库更改的属性(我添加了一个List<X>
到数据模型 Y,其中 X 是一对多关系中的多个。这不会导致数据库更改,因为 X 已经有 Y 的外键)。会是这样吗?如果是这样,那真的很脆弱,因为没有办法为此添加迁移,因为没有数据库更改,而且我也不知道如何解决这个问题。
我不知道如何处理这个问题,因为我当然可以编辑它所搭建的内容并删除已经应用于我的数据库的所有内容。但然后呢?我签入它,然后其他一些开发人员收到相同的消息,即使在应用我的新更改后,他的数据库也不是最新的,搭建他自己的更改,获得相同的废话脚手架,编辑它,签入它,然后next开发人员明白了。它变成了一个恶性循环,与我们使用自动迁移时的情况类似,我认为我们已经通过切换到仅基于代码来解决了这个问题。我现在不能相信它会做正确的事情,与这样的人一起工作是一场噩梦。
我还尝试过添加我从同事那里一一提取的迁移update-database -t:201211091112102_<migrationname>
但无济于事。它仍然给我错误的脚手架。
那么我们在这里做错了什么,或者 EF 根本就不是为这样的协作而构建的?
UPDATE
我创建了一个可重现的测试用例,但为了模拟这个多用户/多数据库场景,这有点漫长。
https://github.com/JulianR/EfMigrationsTest/ https://github.com/JulianR/EfMigrationsTest/
当您拥有上述项目时重现的步骤(这些步骤也存在于代码中):
- 添加迁移初始化
- 更新数据库(在数据库“TestDb”上)
- 更改连接字符串以指向 TestDb1
- TestDb1 上的更新数据库
- 取消类 Test 上的属性 Foo 的注释
- add-migration M1 将属性 Foo 添加到 TestDb1
- 再次注释掉Test.Foo
- 更改连接字符串以指向 TestDb2
- 从项目中排除迁移 M1,以便它不会应用于 TestDb2
- 取消注释类 Test 上的属性 Bar
- 更新数据库以将 Init 迁移应用到 TestDb2
- add-migration M2 将属性 Bar 添加到 TestDb2
- 更改连接字符串以再次指向原始 TestDb
- 再次将迁移M1包含到项目中
- 取消类 Test 上的属性 Foo 的注释
- 取消注释类 Test 上的属性 SomeInt
- 更新数据库
- 添加迁移 M3
- update-database,收到错误,因为 M3 尝试将列 Foo 添加到数据库 TestDb,该数据库刚刚由迁移 M1 添加。
上面是模拟三个用户,其中用户1初始化他的数据库,另外两个用户也使用他的初始化来创建他们的数据库。然后,用户 2 和用户 3 都对数据模型进行自己的更改,并将其与应用更改所需的迁移一起添加到源代码管理中。然后用户 1 拉取用户 2 和 3 的更改,同时用户 1 自己也对数据库进行了更改。然后用户1调用update-database
应用用户 2 和 3 的更改。然后,他搭建自己的迁移,然后错误地将用户 2 或 3 的更改添加到搭建的迁移中,这在应用于用户 1 的数据库时会导致错误。