团队环境中的 Code First 迁移Code First Migrations in Team Environments

备注

本文假设你知道如何在基本方案中使用 Code First 迁移。This article assumes you know how to use Code First Migrations in basic scenarios. 如果没有,则需要先阅读 Code First 迁移 ,然后再继续。If you don’t, then you’ll need to read Code First Migrations before continuing.

抓住咖啡,你需要阅读这篇文章Grab a coffee, you need to read this whole article

团队环境中的问题主要涉及两个开发人员在其本地基本代码中生成迁移时的合并。The issues in team environments are mostly around merging migrations when two developers have generated migrations in their local code base. 虽然解决这些问题的步骤非常简单,但需要您对迁移的工作方式有深刻的了解。While the steps to solve these are pretty simple, they require you to have a solid understanding of how migrations works. 请不要直接跳到结尾–请花时间阅读整篇文章,以确保成功。Please don’t just skip ahead to the end – take the time to read the whole article to ensure you are successful.

一些一般准则Some general guidelines

在深入探讨如何管理由多个开发人员生成的合并迁移之前,下面是一些用于设置成功的一般准则。Before we dig into how to manage merging migrations generated by multiple developers, here are some general guidelines to set you up for success.

每个团队成员都应具有一个本地开发数据库Each team member should have a local development database

迁移使用** _ _ MigrationsHistory**表来存储已应用到数据库的迁移。Migrations uses the __MigrationsHistory table to store what migrations have been applied to the database. 如果有多个开发人员在尝试将同一数据库定向到目标时生成不同的迁移 (,因此共享** _ _ MigrationsHistory**表) 迁移将会变得很混乱。If you have multiple developers generating different migrations while trying to target the same database (and thus share a __MigrationsHistory table) migrations is going to get very confused.

当然,如果您的团队成员不生成迁移,则不会有任何问题与中央开发数据库共享。Of course, if you have team members that aren’t generating migrations, there is no problem having them share a central development database.

避免自动迁移Avoid automatic migrations

最后一行是,自动迁移最初在团队环境中看起来很好,但实际上它们不起作用。The bottom line is that automatic migrations initially look good in team environments, but in reality they just don’t work. 如果希望了解原因,请继续阅读–否则,可以跳到下一部分。If you want to know why, keep reading – if not, then you can skip to the next section.

自动迁移使你能够更新数据库架构以匹配当前模型,而无需生成代码文件 () 的基于代码的迁移。Automatic migrations allows you to have your database schema updated to match the current model without the need to generate code files (code-based migrations). 如果你只使用了这些迁移,并且从未生成任何基于代码的迁移,则自动迁移将在团队环境中正常工作。Automatic migrations would work very well in a team environment if you only ever used them and never generated any code-based migrations. 问题在于自动迁移是有限的,并且不处理多个操作–属性/列重命名、将数据移动到另一个表等。若要处理这些情况,您最终将生成基于代码的迁移 (并编辑在自动迁移处理的更改之间混合的基架代码) 。The problem is that automatic migrations are limited and don’t handle a number of operations – property/column renames, moving data to another table, etc. To handle these scenarios you end up generating code-based migrations (and editing the scaffolded code) that are mixed in between changes that are handled by automatic migrations. 这使得在两个开发人员签入迁移时,无法合并更改。This makes it near on impossible to merge changes when two developers check in migrations.

屏幕广播Screencasts

如果你想要观看 screencast 而不是阅读本文,以下两个视频会涵盖与本文相同的内容。If you'd rather watch a screencast than read this article, the following two videos cover the same content as this article.

视频一: "迁移-在后台"Video One: "Migrations - Under the Hood"

此 screencast 介绍了迁移如何跟踪并使用有关模型的信息来检测模型更改。This screencast covers how migrations tracks and uses information about the model to detect model changes.

视频两个: "迁移-团队环境"Video Two: "Migrations - Team Environments"

根据前一视频中的概念构建, 此 screencast 涵盖了团队环境中出现的问题以及如何解决这些问题。Building on the concepts from the previous video, this screencast covers the issues that arise in a team environment and how to solve them.

了解迁移的工作方式Understanding how migrations works

在团队环境中成功使用迁移的关键是要了解迁移如何跟踪并使用有关模型的信息来检测模型更改。The key to successfully using migrations in a team environment is a basic understanding how migrations tracks and uses information about the model to detect model changes.

第一次迁移The first migration

将首次迁移添加到项目时,会在程序包管理器控制台中首先运行类似于 添加迁移 的操作。When you add the first migration to your project, you run something like Add-Migration First in Package Manager Console. 此命令执行的高级步骤如下图所示。The high level steps that this command performs are pictured below.

首次迁移

当前模型是从代码 (1) 计算得出的。The current model is calculated from your code (1). 然后,模型会 (2) 来计算所需的数据库对象–因为这是第一次迁移模型不同只是使用空模型进行比较。The required database objects are then calculated by the model differ (2) – since this is the first migration the model differ just uses an empty model for the comparison. 所需的更改会传递给代码生成器,以生成 (3) 所需的迁移代码,然后将其添加到 Visual Studio 解决方案 (4) 。The required changes are passed to the code generator to build the required migration code (3) which is then added to your Visual Studio solution (4).

除了存储在主代码文件中的实际迁移代码外,迁移还会生成一些附加的代码隐藏文件。In addition to the actual migration code that is stored in the main code file, migrations also generates some additional code-behind files. 这些文件是迁移使用的元数据,而不是你应该编辑的内容。These files are metadata that is used by migrations and are not something you should edit. 其中一项文件是资源文件 ( .resx) ,该文件包含在生成迁移时模型的快照。One of these files is a resource file (.resx) that contains a snapshot of the model at the time the migration was generated. 下一步将介绍如何使用此方法。You’ll see how this is used in the next step.

此时,你可能会运行 " 更新数据库 " 以将更改应用到数据库,然后再开始实现应用程序的其他区域。At this point you would probably run Update-Database to apply your changes to the database, and then go about implementing other areas of your application.

后续迁移Subsequent migrations

稍后返回并对模型进行一些更改-在本示例中,我们会将 Url 属性添加到 博客Later you come back and make some changes to your model – in our example we’ll add a Url property to Blog. 然后,将发出一个命令(如 添加迁移 AddUrl )基架迁移,以应用相应的数据库更改。You would then issue a command such as Add-Migration AddUrl to scaffold a migration to apply the corresponding database changes. 此命令执行的高级步骤如下图所示。The high level steps that this command performs are pictured below.

第二次迁移

与上一次一样,当前模型是从代码 (1) 计算得出的。Just like last time, the current model is calculated from code (1). 但是,这一次存在现有的迁移,因此从最新迁移 (2) 中检索上一个模型。However, this time there are existing migrations so the previous model is retrieved from the latest migration (2). 这两个模型 diffed,用于查找 (3) 所需的数据库更改,然后该进程将像以前一样完成。These two models are diffed to find the required database changes (3) and then the process completes as before.

此过程用于添加到项目中的任何其他迁移。This same process is used for any further migrations that you add to the project.

为什么要干扰模型快照?Why bother with the model snapshot?

您可能想知道 EF 为什么要麻烦模型快照–为什么不只是查看数据库。You may be wondering why EF bothers with the model snapshot – why not just look at the database. 如果是这样,请继续阅读。If so, read on. 如果你不感兴趣,则可以跳过此部分。If you’re not interested then you can skip this section.

EF 保留模型快照的原因有很多:There are a number of reasons EF keeps the model snapshot around:

  • 它允许您的数据库与 EF 模型的偏差。It allows your database to drift from the EF model. 可以直接在数据库中进行这些更改,也可以更改迁移中的基架代码以进行更改。These changes can be made directly in the database, or you can change the scaffolded code in your migrations to make the changes. 下面是其中几个示例:Here are a couple of examples of this in practice:
    • 您希望向一个或多个表中添加插入的和更新的到列,但不希望在 EF 模型中包含这些列。You want to add an Inserted and Updated to column to one or more of your tables but you don’t want to include these columns in the EF model. 如果迁移过程中查看了数据库,则每次基架迁移时,它都会不断尝试删除这些列。If migrations looked at the database it would continually try to drop these columns every time you scaffolded a migration. 使用模型快照,EF 只会检测到对模型的合法更改。Using the model snapshot, EF will only ever detect legitimate changes to the model.
    • 要更改用于更新的存储过程的正文,以包含一些日志记录。You want to change the body of a stored procedure used for updates to include some logging. 如果迁移从数据库中查看此存储过程,它将继续尝试并将其重置回 EF 需要的定义。If migrations looked at this stored procedure from the database it would continually try and reset it back to the definition that EF expects. 通过使用模型快照,在 EF 模型中更改过程的形状时,EF 只会基架代码来更改存储过程。By using the model snapshot, EF will only ever scaffold code to alter the stored procedure when you change the shape of the procedure in the EF model.
    • 这些相同的原则适用于添加额外的索引,包括数据库中的额外表、将 EF 映射到表中的数据库视图等。These same principles apply to adding extra indexes, including extra tables in your database, mapping EF to a database view that sits over a table, etc.
  • EF 模型只包含数据库的形状。The EF model contains more than just the shape of the database. 整个模型允许迁移查看有关模型中的属性和类的信息,以及它们如何映射到这些列和表。Having the entire model allows migrations to look at information about the properties and classes in your model and how they map to the columns and tables. 此信息允许在基架的代码中更智能地迁移。This information allows migrations to be more intelligent in the code that it scaffolds. 例如,如果您更改属性映射到迁移的列的名称,则可以通过查看它是相同的属性来检测重命名,如果只有数据库架构,则无法执行此操作。For example, if you change the name of the column that a property maps to migrations can detect the rename by seeing that it’s the same property – something that can’t be done if you only have the database schema. 

导致团队环境中出现问题的原因What causes issues in team environments

当你是处理应用程序的单个开发人员时,上一部分介绍的工作流非常有用。The workflow covered in the previous section works great when you are a single developer working on an application. 如果您是更改模型的唯一人员,它在团队环境中也能正常工作。It also works well in a team environment if you are the only person making changes to the model. 在这种情况下,你可以进行模型更改,生成迁移并将它们提交到源控件。In this scenario you can make model changes, generate migrations and submit them to your source control. 其他开发人员可以同步您的更改并运行 更新数据库 ,以应用架构更改。Other developers can sync your changes and run Update-Database to have the schema changes applied.

当你有多个开发人员更改 EF 模型并同时提交到源代码管理中时,就会出现问题。Issues start to arise when you have multiple developers making changes to the EF model and submitting to source control at the same time. EF 缺乏哪一种方法是将本地迁移与其他开发人员自上次同步后已提交到源代码管理的迁移合并在一起。What EF lacks is a first class way to merge your local migrations with migrations that another developer has submitted to source control since you last synced.

合并冲突的示例An example of a merge conflict

首先,让我们看一看此类合并冲突的具体示例。First let’s look at a concrete example of such a merge conflict. 我们会继续学习前面所述的示例。We’ll continue on with the example we looked at earlier. 作为起点,假设先前部分中的更改已由原始开发人员签入。As a starting point let’s assume the changes from the previous section were checked in by the original developer. 我们将在两个开发人员更改代码库时进行跟踪。We’ll track two developers as they make changes to code base.

我们将通过多个更改跟踪 EF 模型和迁移。We’ll track the EF model and the migrations thru a number of changes. 对于起始点,这两个开发人员已同步到源代码管理存储库,如下图所示。For a starting point, both developers have synced to the source control repository, as depicted in the following graphic.

起点

开发人员 # 1 和开发人员 # 2 现在会在其本地代码库中对 EF 模型进行一些更改。Developer #1 and developer #2 now makes some changes to the EF model in their local code base. 开发人员 # 1 将 分级 属性添加到 博客 –并生成 AddRating 迁移,以将更改应用到数据库。Developer #1 adds a Rating property to Blog – and generates an AddRating migration to apply the changes to the database. 开发人员 # 2 将 读者 属性添加到 博客 –并生成相应的 AddReaders 迁移。Developer #2 adds a Readers property to Blog – and generates the corresponding AddReaders migration. 这两个开发人员都运行 更新数据库,以将更改应用到本地数据库,然后继续开发应用程序。Both developers run Update-Database, to apply the changes to their local databases, and then continue developing the application.

备注

迁移以时间戳为前缀,因此我们的图形表示从 # 开发人员1开始的 AddRating 迁移后,开发人员2的 AddReaders 迁移 # 。Migrations are prefixed with a timestamp, so our graphic represents that the AddReaders migration from Developer #2 comes after the AddRating migration from Developer #1. 开发人员 # 1 或 # 2 是否首先生成了迁移,与团队中工作的问题或合并过程的过程没有什么不同,我们将在下一节中进行讨论。Whether developer #1 or #2 generated the migration first makes no difference to the issues of working in a team, or the process for merging them that we’ll look at in the next section.

本地更改

这是开发人员1幸运的一天, # 因为他们首先提交其更改。It’s a lucky day for Developer #1 as they happen to submit their changes first. 由于其他人在同步其存储库后未签入,因此他们只需提交其更改而无需执行任何合并。Because no one else has checked in since they synced their repository, they can just submit their changes without performing any merging.

提交更改

现在是时候开发人员2的时候了 # 。Now it’s time for Developer #2 to submit. 它们不太幸运。They aren’t so lucky. 由于其他人已在同步后提交了更改,因此他们将需要下拉更改并进行合并。Because someone else has submitted changes since they synced, they will need to pull down the changes and merge. 源代码管理系统可能会自动将更改合并到代码级别,因为它们非常简单。The source control system will likely be able to automatically merge the changes at the code level since they are very simple. #在同步后,开发人员2的本地存储库的状态如下图所示。The state of Developer #2’s local repository after syncing is depicted in the following graphic. 

从源控件拉取

在此阶段,开发人员 # 2 可以运行 更新数据库 ,该数据库将检测到尚未应用于 Developer 2 的数据库的新 AddRating 迁移 (#) 并应用该迁移。At this stage Developer #2 can run Update-Database which will detect the new AddRating migration (which hasn’t been applied to Developer #2’s database) and apply it. 现在," 评级 " 列将添加到 " 博客 " 表中,并且数据库与模型同步。Now the Rating column is added to the Blogs table and the database is in sync with the model.

但有几个问题:There are a couple of problems though:

  1. 尽管 " 更新-数据库 " 将应用 AddRating 迁移,但它还会引发警告: 无法更新数据库以匹配当前模型,因为存在挂起的更改,并且禁用了自动迁移 ...Although Update-Database will apply the AddRating migration it will also raise a warning: Unable to update database to match the current model because there are pending changes and automatic migration is disabled… 问题在于,上一次迁移 (AddReader) 中存储的模型快照缺少博客 (上的分级属性,因为它不是生成迁移) 时的模型的一部分。The problem is that the model snapshot stored in the last migration (AddReader) is missing the Rating property on Blog (since it wasn’t part of the model when the migration was generated). Code First 检测到上一次迁移中的模型与当前模型不匹配,并引发警告。Code First detects that the model in the last migration doesn’t match the current model and raises the warning.
  2. 运行应用程序会导致 InvalidOperationException,指出 "" bloggingcontext "" 上下文的模型在创建数据库后已发生更改。请考虑使用 Code First 迁移更新数据库 ... "Running the application would result in an InvalidOperationException stating that “The model backing the 'BloggingContext' context has changed since the database was created. Consider using Code First Migrations to update the database…” 同样,问题在于上一次迁移中存储的模型快照与当前模型不匹配。Again, the problem is the model snapshot stored in the last migration doesn’t match the current model.
  3. 最后,我们希望运行 添加迁移 现在会生成一个空的迁移 (,因为没有要应用到数据库) 的更改。Finally, we would expect running Add-Migration now would generate an empty migration (since there are no changes to apply to the database). 但是,因为迁移会将当前模型与上一次迁移 ((缺少 分级 属性)的模型进行比较,) 它将实际基架另一次 AddColumn 调用以添加到 分级 列中。But because migrations compares the current model to the one from the last migration (which is missing the Rating property) it will actually scaffold another AddColumn call to add in the Rating column. 当然,此迁移将在 更新数据库 过程中失败,因为 " 分级 " 列已经存在。Of course, this migration would fail during Update-Database because the Rating column already exists.

解决合并冲突Resolving the merge conflict

好消息是,如果你对迁移的工作方式有所了解,就不难手动处理合并了。The good news is that it’s not too hard to deal with the merge manually – provided you have an understanding of how migrations works. 如果您跳过此部分,So if you’ve skipped ahead to this section… 抱歉,您需要返回本文的剩余部分!sorry, you need to go back and read the rest of the article first!

有两个选项,最简单的方法是生成一个将正确的当前模型作为快照的空白迁移。There are two options, the easiest is to generate a blank migration that has the correct current model as a snapshot. 第二个选项是更新上一次迁移中的快照,使其具有正确的模型快照。The second option is to update the snapshot in the last migration to have the correct model snapshot. 第二个选项更难,不能用于每个方案中,但它也更清晰,因为它不涉及添加额外的迁移。The second option is a little harder and can’t be used in every scenario, but it’s also cleaner because it doesn’t involve adding an extra migration.

选项1:添加空白 "合并" 迁移Option 1: Add a blank ‘merge’ migration

在此选项中,我们将仅生成一个空白迁移,目的是确保最新迁移中存储了正确的模型快照。In this option we generate a blank migration solely for the purpose of making sure the latest migration has the correct model snapshot stored in it.

无论上次迁移的用户是谁,都可以使用此选项。This option can be used regardless of who generated the last migration. 在本示例中,我们已关注开发人员 # 2 正在处理合并,并且它们会生成上次迁移。In the example we’ve been following Developer #2 is taking care of the merge and they happened to generate the last migration. 但是,如果开发人员 # 1 生成了上一次迁移,则可以使用这些相同的步骤。But these same steps can be used if Developer #1 generated the last migration. 如果涉及多个迁移,则这些步骤也适用–我们只需查看两个步骤,使其保持简单。The steps also apply if there are multiple migrations involved – we’ve just been looking at two in order to keep it simple.

以下过程可用于此方法,从你认识到需要从源控件同步的更改开始。The following process can be used for this approach, starting from the time you realize you have changes that need to be synced from source control.

  1. 确保已将本地代码库中的任何挂起的模型更改写入迁移。Ensure any pending model changes in your local code base have been written to a migration. 此步骤可确保在生成空白迁移时不会遗漏任何合法更改。This step ensures you don’t miss any legitimate changes when it comes time to generate the blank migration.
  2. 与源代码管理同步。Sync with source control.
  3. 运行 " 更新-数据库 " 以应用其他开发人员已签入的任何新迁移。Run Update-Database to apply any new migrations that other developers have checked in. 注意: 如果你没有从更新-数据库命令收到任何警告,则没有来自其他开发人员的新迁移,无需执行任何进一步的合并。Note: if you don’t get any warnings from the Update-Database command then there were no new migrations from other developers and there is no need to perform any further merging.
  4. 运行 添加迁移 < 选取 _ 一个 _ 名称 > – IgnoreChanges (例如, add-迁移 Merge – IgnoreChanges) 。Run Add-Migration <pick_a_name> –IgnoreChanges (for example, Add-Migration Merge –IgnoreChanges). 这将生成一个包含所有元数据 (的迁移,其中包括当前模型的快照) 但在将当前模型与上一次迁移中的快照进行比较时,将忽略它检测到的任何更改 (也就是说,你将获得一个空的 向上向下 方法) 。This generates a migration with all the metadata (including a snapshot of the current model) but will ignore any changes it detects when comparing the current model to the snapshot in the last migrations (meaning you get a blank Up and Down method).
  5. 运行 Update-Database ,以使用更新的元数据重新应用最新的迁移。Run Update-Database to re-apply the latest migration with the updated metadata.
  6. 运行课程) 的单元测试后,继续开发或提交到源代码管理 (。Continue developing, or submit to source control (after running your unit tests of course).

下面是 # 使用此方法后开发人员2的本地代码库的状态。Here is the state of Developer #2’s local code base after using this approach.

合并迁移

选项2:在上一次迁移中更新模型快照Option 2: Update the model snapshot in the last migration

此选项与选项1非常相似,但会删除额外的空白迁移,因为让我们面对自己的解决方案,需要额外的代码文件。This option is very similar to option 1 but removes the extra blank migration – because let’s face it, who wants extra code files in their solution.

**此方法仅在以下情况下可行:仅在本地代码库中存在最新的迁移,并且尚未提交到源代码管理 (例如,如果执行合并) 的用户生成了最后一个迁移 **。This approach is only feasible if the latest migration exists only in your local code base and has not yet been submitted to source control (for example, if the last migration was generated by the user doing the merge). 编辑其他开发人员可能已应用于其开发数据库(甚至更糟)的迁移的元数据可能会导致意外的副作用。Editing the metadata of migrations that other developers may have already applied to their development database – or even worse applied to a production database – can result in unexpected side effects. 在此过程中,我们将在本地数据库中回滚上一次迁移,并使用更新的元数据重新应用它。During the process we’re going to roll back the last migration in our local database and re-apply it with updated metadata.

虽然最后的迁移需要位于本地代码库中,但在此过程中,迁移的数量或顺序并没有限制。While the last migration needs to just be in the local code base there are no restrictions to the number or order of migrations that proceed it. 可以从多个不同的开发人员进行多个迁移,相同的步骤同样适用–我们一直在寻找两个,使其保持简单。There can be multiple migrations from multiple different developers and the same steps apply– we’ve just been looking at two in order to keep it simple.

以下过程可用于此方法,从你认识到需要从源控件同步的更改开始。The following process can be used for this approach, starting from the time you realize you have changes that need to be synced from source control.

  1. 确保已将本地代码库中的任何挂起的模型更改写入迁移。Ensure any pending model changes in your local code base have been written to a migration. 此步骤可确保在生成空白迁移时不会遗漏任何合法更改。This step ensures you don’t miss any legitimate changes when it comes time to generate the blank migration.
  2. 与源代码管理同步。Sync with the source control.
  3. 运行 " 更新-数据库 " 以应用其他开发人员已签入的任何新迁移。Run Update-Database to apply any new migrations that other developers have checked in. 注意: 如果你没有从更新-数据库命令收到任何警告,则没有来自其他开发人员的新迁移,无需执行任何进一步的合并。Note: if you don’t get any warnings from the Update-Database command then there were no new migrations from other developers and there is no need to perform any further merging.
  4. 运行TargetMigration < 第二 _ 次 _ 迁移 > ** (在下面的示例中,我们要做的就是更新-数据库– TargetMigration AddRating**) 。Run Update-Database –TargetMigration <second_last_migration> (in the example we’ve been following this would be Update-Database –TargetMigration AddRating). 这会将数据库回滚到第二次迁移的状态,这实际上是从数据库中 "取消应用" 最后一次迁移。This rolls the database back to the state of the second last migration – effectively ‘un-applying’ the last migration from the database. 注意: 若要安全地编辑迁移的元数据,需要执行此步骤,因为元数据也存储在数据库的 _ _ MigrationsHistoryTable 中。这就是仅当最后一次迁移仅在本地代码库中时才应使用此选项的原因。如果其他数据库应用了上次迁移,则还必须将其回滚并重新应用上次迁移以更新元数据。Note: This step is required to make it safe to edit the metadata of the migration since the metadata is also stored in the __MigrationsHistoryTable of the database. This is why you should only use this option if the last migration is only in your local code base. If other databases had the last migration applied you would also have to roll them back and re-apply the last migration to update the metadata. 
  5. 运行添加迁移 < 全名 _ _ (包括 _ _ _ 上次 _ 迁移的时间戳) > (在下面的示例中,这可能类似于添加迁移 201311062215252 _ AddReaders) 。Run Add-Migration <full_name_including_timestamp_of_last_migration> (in the example we’ve been following this would be something like Add-Migration 201311062215252_AddReaders). 注意: 需要包含时间戳,以便迁移知道要编辑现有迁移,而不是新的基架。Note: You need to include the timestamp so that migrations knows you want to edit the existing migration rather than scaffolding a new one. 这将更新上一次迁移的元数据以匹配当前模型。This will update the metadata for the last migration to match the current model. 当命令完成时,你将收到以下警告,但这正是你所希望的。You’ll get the following warning when the command completes, but that’s exactly what you want. "只有迁移" 201311062215252 AddReaders "的设计器代码 _ 是重新基架的。若要重新基架整个迁移,请使用-Force 参数。 "Only the Designer Code for migration '201311062215252_AddReaders' was re-scaffolded. To re-scaffold the entire migration, use the -Force parameter.”
  6. 运行 Update-Database ,以使用更新的元数据重新应用最新的迁移。Run Update-Database to re-apply the latest migration with the updated metadata.
  7. 运行课程) 的单元测试后,继续开发或提交到源代码管理 (。Continue developing, or submit to source control (after running your unit tests of course).

下面是 # 使用此方法后开发人员2的本地代码库的状态。Here is the state of Developer #2’s local code base after using this approach.

更新的元数据

总结Summary

在团队环境中使用 Code First 迁移时,需要一些挑战。There are some challenges when using Code First Migrations in a team environment. 不过,基本了解迁移的工作方式,以及解决合并冲突的一些简单方法,可以轻松地克服这些难题。However, a basic understanding of how migrations works and some simple approaches for resolving merge conflicts make it easy to overcome these challenges.

基本问题是最新迁移中存储的元数据不正确。The fundamental issue is incorrect metadata stored in the latest migration. 这会导致 Code First 错误检测到当前模型和数据库架构不匹配,也不会在下一次迁移中基架错误代码。This causes Code First to incorrectly detect that the current model and database schema don’t match and to scaffold incorrect code in the next migration. 通过使用正确的模型生成空白迁移,或在最新的迁移中更新元数据,可以解决这种情况。This situation can be overcome by generating a blank migration with the correct model, or updating the metadata in the latest migration.