Migrations in Entity Framework in a collaborative environment

大城市里の小女人 提交于 2019-11-27 06:37:17

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.

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

Add-Migration M2

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.

You need to add a blank "merge" migration that will reset the snapshot of the latest migration in the .resx file. Do this using the IgnoreChanges switch:

Add-Migration <migration name> -IgnoreChanges

See here for an explanation

SharmaPattar

Option 1: Add a blank ‘merge’ migration

  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. Run Add-Migration –IgnoreChanges (e.g. 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. Continue developing, or submit to source control (after running your unit tests of course).

Option 2: Update the model snapshot in the last migration

  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. Run Update-Database –TargetMigration (in the example we’ve been following this would be Update-Database –TargetMigration AddRating). This roles the database back to the state of the second last migration – effectively ‘un-applying’ the last migration from the database. ** 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. Run Add-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. “Only the Designer Code for migration '201311062215252_AddReaders' was re-scaffolded. To re-scaffold the entire migration, use the -Force parameter.”
  6. 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).

MSDN have a great article on this. Please go through it.

Entity Framework Code First Migrations in Team Environments

We are having similar issues in our environment, here is what we've figured out so far and how we got around it:

When you have changes that you have applied (update-database) but not checked in, and then you receive changes from another developer who doesn't have your changes, this is where things seem to get out of sync. In our experience, it seems like the meta data that is saved for your own changes get over written by the meta-data from the other developer when you do the update-database process. The other developer doesn't have your changes, so the meta-data that gets saved is no longer a real reflection of your database. When EF does a comparison after that, it 'thinks' that your changes are actually new again because of the meta data change.

A simple, admittedly ugly workaround is to do another migration, and wipe out it's contents so you have empty up() and empty down() methods. Apply that migration and check it into source control and let everyone sync to that. This simply syncs up all of the meta data so everyone has all of the changes accounted for.

I have added an issue on codeplex, this issue causes many a head scratching in our team too.

The link is https://entityframework.codeplex.com/workitem/1670

I have put some thought into this and I hope I will contribute to the different opinions and practices presented here.

Consider what your local migrations actually represent. When working locally with a dev database, I use migrations to update the database in the most convenient way possible when adding columns etc to tables, adding new entities etc.

So, Add-Migration checks my current model (let's call it model b) against my previous model (model a) and generates a migration to go from a => b in the database.

To me it makes very little sense to try and merge my migrations with anyone elses migrations, if everyone indeed has their own database and there then exists some kind of stage / test / dev / production database servers in the organization. This all depends on how the team has it set up, but it makes sense to insulate each other from changes that other people make if you want to truly work in a distributed manner.

Well, if you work distributed and have some entity, Person, for example, that you work on. For some reason, lots of other people are also working on it. So, you add and remove properties on Person as needed for your particular story in the sprint (we're all working agile here, aren't we?), like Social Security number that you first made into an integer because you aren't that bright and then to a string etc.

You add FirstName And LastName.

You are then done and you have ten weird up and down migrations (you probably removed some of them while working since they were just crap) and you fetch some changes from the central Git repo. Wow. Your colleague Bob also needed some names, maybe you should've talked to each other?

Anyways, he has added NameFirst and NameLast, I guess... so what do you do? Well, you merge, refactor, change so it has more sane names... like FirstName and LastName, you run your tests and check his code, and then you push to the central.

But what about the migrations? Well, now would be the time to make a migration moving the central repo, or the branch "test" more specifically, contain a nice little migration from its model a => model b. This migration will be one and only one migration, not ten weird ones.

Do you see what I'm getting at? We are working with nice little pocos and the comparisons of them constitute the actual migrations. So, we shouldn't merge migrations at all, in my opinion, we should have migrations-per-branch or something like that.

In fact, do we even need to create the migration in the branch after merge? Yes, if this database is updated automatically, we need to.

Another thing to consider is to never actually creating a migration before doing a pull from the central repo. That means you will both get the other team members' migration code and their changes to the model before creating your migration.

Gotta work some more, those are my thoughts on this, at least.

user2965947

The solution I was able to come up with (at least for 2 users, haven't tested for 3) is:

  1. merging migrations to sync up the meta-data run update-database (this should fail), then
  2. add-database and then
  3. delete all of the generated code in up() and down() methods

this will still be run by update database but won't do anything, just bringing the metadata up to sync.

I agree with @LavaEater. The core of the issue, it would seem, is that migration scaffolding should be centralised. Perhaps as part of some automated/integrated build process each time a push occurs? Thereafter the resulting migrations can be pulled from the server by team-members.

This means that their own migration scripts should not be pushed to the server.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!