Not using code first migrations - c#

I love code first. But here and then facing contraint problems and such , that makes me drop database and recreate etc.
My concern is that, once in production, i cant do that.
Is it possible not to use code first migrations and just creating fields by hand at database/tables?
That also makes me worry for foreign key constraints again.
What is the best way to do this?

If you use EF < 4.3 you can recreate database on dev server and manual update production database in two step:
creating fields by hand at tables
update EdmMetadata table (use data form dev database)
Else use code first migrations : update-database -script,
This command generate update script for you database, and you can do it manually.

At about 4:20, the tutorial video at the Microsoft website starts talking about Migrations
http://msdn.microsoft.com/en-us/data/jj193542.aspx

Related

Handling code-first database migrations that fail halfway

My company has tasked me with figuring out if we want to use EF6 for some new applications. I've done some testing, and I get the general idea of most aspects, but the database updates generated by code-first migrations worry me.
I have a database with 3 tables. A 4th was added, and the 3 existing tables received a foreign key to this table. I generated an update script and ran it. But I made a mistake. This happened:
The new table was generated.
The foreign key was added to the first existing table.
The second table had existing data, and I forgot to specify a default value for the foreign key, so the update failed at this point.
I now have a partially updated database, which to me is a Really Bad Thing. The EF6 system has no idea at this point what it did and did not execute, and if I somehow lose the migration error, neither do I. The only way I could find to fix this was:
Figure out which update statement cause the error.
Manually undo the changes in the database that were executed before the faulty statement was hit .
Run the migration again and hope I got it right this time.
Manually fixing the database was relatively easy, since I only added things. If the migration had for example removed some columns, it would have been way more difficult to revert the changes. Furthermore, a migration like this could very well run without trouble on a development machine that has no data in its tables and suddenly fail when deploying to a testing environment (or worse).
If we are going to use this framework, we need to be sure that there's no way that anyone can accidentally corrupt a database. So my question is: how do people handle issues like these with EF6? Should I just always use the -Script parameter to run the updates manually one by one? Do I just suck it up and triple check all migrations? Is there a better way to deal with this?
I hope the question is clear and I'm looking forward to any insight.

Create SQL View With Entity Framework 6 Code First

I am new to Entity Framework 6 Code First and am trying to perform what I thought would be a simple task. I want to create a SQL View and then have an Entity in my database context that I can use to query the view.
I have tried articles such as this but the key difference in my case is that the SQL View is not an existing view coming from another existing database.
I examined the proposition made in this article but it seems like overkill to me that I would need to create some extension methods to do something as simple as create a view/entity combo and use it in my database context.
Am I missing something? I know it would be much easier if I weren't using Code First but please keep in mind it's Code First and I am trying to create a view, not reuse one from an existing database.
Colin and Kevin, Thank you for the link to your answer on the other post and your concise answer. I have used several resources to finally create a queryable entity based on a new SQL view. Just in case anyone else is new to EF 6.0 Code First and is just getting their feet wet, I do have a few steps that will hopefully benefit others in the future.
It may seem obvious to more seasoned Entity Framework developers, but in order to execute the 'Migration' approach you need to disable automatic migrations and actually dive into the guts of the Code First Migrations inner workings. Since automatic migrations is turned on out of the box, I had already created a fairly complex database with seed scripts all relying on automatic migrations and rebuilding the database on every run of my application. This post helped me wipe my migrations history and get to square 1 with automatic migrations turned off (I went with the web.config approach in case you were wondering)
After I had cleared my migrations information, I deleted the mdf from within solution explorer. That guaranteed that I wouldn't run into any problems when running Update-Database (further down the list of steps).
In the Package Manger console, I then executed Add-Migration Initial to generate an "Initial" migration. The result of this was the editable Up and Down methods as described in Colin's answer. I then followed the steps in Colin's answer by commenting out the table create statement (Entity Framework tries to create a table but we really want to create a view and map it to the Entity) and inserting my own view create sql statement at the end of the Up method. It's important to put the create statement after the creation of any tables that it may depend on. I also performed my Seed activities in the Configuration.Seed method instead of in my Context's Seed method. I see how this would be important if you were dealing with multiple migrations. Finally, as Colin suggested I added the table mapping to my context's OnModelCreating event.
The final step in this was to actually apply the migration to the database. In order to do that, in the Package Manager console you execute the Update-Database command. That statement will rebuild the database with the "Initial" migration you created and edited in earlier steps.
It still surprises me that I need to do all of this custom work to create a view and map it to an entity with Code First, but at the end of the day it was helpful in getting me started on migrations as you can only rely on the "automatic migrations" for so long anyways.
You can manually add the sql to create the view to a migration then consume it as per your first link.
The answer in the link provided by Colin does the job.
In case there are lots of views to be created, it can be a good idea to save the view queries in separate files and add them in a resource (.resx) file instead of hard-coding the sql queries in the Migration Up() method.
For e.g.
public override void Up()
{
Sql("ResourceFileName.ResourceName");
}
instead of hard coding like
{
Sql("EXEC ('CREATE View [dbo].[ClientStatistics] AS --etc");
}

Removing all automatic migrations and creating code-based migrations in their place

As you're about to learn, I'm inexperienced with building applications using ASP.NET MVC, I'm deliberately coming out of my comfort zone in order to learn.
I'm using code-first migrations with Entity Framework, and I created a Train.cs model and used the Enable-Migrations command. For some reason I thought it would be a good idea to enable automatic migrations in Migrations/Configuration.cs and I continued developing with automatic migrations enabled for a while.
Then I read somewhere that automatic migrations are generally a bad thing, so I disabled them. My Train model needed a new field called Description, so I added it. I ran Add-Migration AddDescriptionToTrains, then did Update-Database. It's throwing me back this error:
Cannot find the object "dbo.Trains" because it does not exist or you do not have permissions.
I think this is happening because I deleted the mdf file that was under App_Data in order to wipe out my database and start fresh, and it doesn't have a migration to create the Trains table before it tried to add a Description field to it.
Basically my question is, can I delete all of my migrations down to InitialCreate, and then just generate one from my model? I only have one model so it should only create one migration. I just want to create the migration from the entire model, not what it thinks has changed in the model.
In short, yes you can. In my experience, anytime you can delete the content of the _MigrationsHistory table and restart generating migrations.

How to force EF code first to recreate databases?

I had a bunch of tables Code First created.
Then in SQL i deleted one table so that i could inevitably ask this question on stack.
Upon using update-database in package management console I get:
Cannot find the object "dbo.ContractParents" because it does not exist
or you do not have permissions.
What is the best way to recreate my table?
I've read up about context.Database.CreateIfNotExists();
I put it in my seed function, but nothing doing.
Thanks!
To explain what happens with your update-database command and why the context.Database.CreateIfNotExists() method in the seed did not work:
When you run the update-database command it first looks at your connection string to see if the database is there. If it is it looks at the migration history table and checks that against what is in you DbContext class. If it sees that there are tables missing or changes it will attempt to update the database. The Seed method is not called until after that is done, so that is why that did not work.
While developing using EF-Code First I usually approach the problem in a few different ways depending on how large my database is. I usually went the route of deleting all the tables (including the migration history table) and then running the update-database command again. Works fine, just really time consuming if you have a lot of tables with a lot of FK constraints on it.
I finally became tired of it and found these scripts to make the dropping of tables exponentially faster. I went to this because I was running my app on Azure. When I am running it on my local machine, I would just delete the whole database and make a brand new database with the same name.
Elegant solution? No.
Does it work? More or less...
For yet another cheesy option...
Right click on your db in server explorer, and hit delete
Then you can do
Enable-Migrations -EnableAutomaticMigrations -Force
Update-Database -Force
Dirty update, clean result :)
For a quick and dirty approach, that'll get you home for dinner on time along with lots of dataloss (i'm still in beta using test data)
drop the dbo.__MigrationHistory system table
along with all of your other tables.
Back up your data first!
update-database -verbose (you may need some sauce with your spaghetti)
I am not impressed, but it works.
Hopefully someone will come up with a better answer in the future.
It would help to really understand migrations better.

Migrations in Entity Framework in a collaborative environment

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.
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:
Developer changes his datamodel
Does add-migration <Name> and applies it to his database with update-database.
Checks in the datamodel change and the migration into Git.
Another developer pulls, receives the changes and applies it to his 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.
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.
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.
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.
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.
So what did we do wrong here, or is EF simply not built for collaboration like this?
UPDATE
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):
add-migration Init
update-database (on database 'TestDb')
Change connection string to point to TestDb1
update-database on TestDb1
Uncomment property Foo on class Test
add-migration M1 to add property Foo to TestDb1
Comment out Test.Foo again
Change connection string to point to TestDb2
Exclude migration M1 from project so it doesn't get applied to TestDb2
Uncomment property Bar on class Test
update-database to apply Init migration to TestDb2
add-migration M2 to add property Bar to TestDb2
Change connection string to point to the original TestDb again
Include migration M1 into the project again
Uncomment property Foo on class Test
Uncomment property SomeInt on class Test
update-database
add-migration M3
update-database, get an error because M3 tries to add column Foo to database TestDb which was already just added by migration M1.
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.
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
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.
Option 1: Add a blank ‘merge’ migration
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.
Sync with source control.
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.
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).
Continue developing, or submit to source control (after running your
unit tests of course).
Option 2: Update the model snapshot in the last migration
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.
Sync with the source control.
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.
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.
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.”
Run Update-Database to
re-apply the latest migration with the updated metadata.
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.
The solution I was able to come up with (at least for 2 users, haven't tested for 3) is:
merging migrations to sync up the meta-data run update-database (this should fail), then
add-database and then
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.
There is an easy way to have no merge conflicts/errors with migrations.
Work on your branch as you would do at any time.
If you merge to master and have merge errors then:
remove all *.cs files from migrations folder.
do git checkout master ./* inside migrations folder.
Recreate your migration.
Your snapshot is up2date and there is no merge conflict.
Also just before merging pull request to master you need to merge with master and do steps 3-6 ALWAYS.
Below is simple Powershell script that does steps 3-6:
function Write-Info($text)
{
Write-Color "$pwd", "> ", "$text" -Colour "Yellow", "Blue", "White"
}
function Create-Migration($project, $migrationName, $referenceBranch)
{
Set-Location "$SolutionPath\$project"
Write-Info "Going to migrations"
Set-Location "Migrations"
Write-Info "Removing ./*.cs"
Remove-Item ./*.cs
Write-Info "git fetch --all"
git fetch --all
Write-Info "git checkout origin/$referenceBranch ./*"
git checkout origin/$referenceBranch ./*
Set-Location ..
Write-Info "Creating migration $migrationName "
dotnet ef migrations add "$migrationName"
}
I am working with that method for last half year. 0 merge conflicts to resolve when it comes to migrations 8).

Categories

Resources