How to initialize EF Code First Migrations on a remote target - entity-framework

I would like to introduce Code First Migrations to my project, but I am unsure of how to handle deploying this to my client for testing. Until now, things have been quite simple, and I have just used a CreateDatabaseIfNotExists initializer. Now, I have two scenarios:
He deletes his existing, before-migrations, database, and uses an initializer to create a new, with-migrations, database, and we use migrations from here on to upgrade his database. Can I use the MigrateDatabaseToLatestVersion initializer to create the DB if missing as well?
I just deploy my code and let it perform migrations. I'm not quite sure if anything but using a MigrateDatabaseToLatestVersion is required here. Will this upgrade a pre-migrations database to one suitable for migrations?

This is what I do when automatic migration is required; I hope this helps you find a solution:
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<ContextFileName, PathToMigrationsConfig>()
);
Database.Initialize(false);
In the configuration file for the migrations, I set the following in the constructor
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = false;
In the configuration file you should have an override of the seed method, if not you can add it and fill in your seed data.
What the above will do is create/upgrade the database to the latest as long as no data loss occurs. This should allow you hand off the code to the client.
On a side note, for a production system I will usually argue the point of not doing this. This had many disadvantages. For databases I do not have control over I have yet to find a client that has refused the generated script file.
You can get this by using the following command after you add a migration through the Package Manager Console:
Update-database –script -verbose

Related

Getting EF Context has Changed Error After Updating Site

I am having an issue where I am getting an error "context has changed since the database was created," but when I look at the migrations history table it is the latest migration. This is a test site, so I updated the database using a sql script I got by running this command "Update-Database -Script -SourceMigration: $InitialDatabase" I can't just delete the whole database and recreate it. Has anyone run into a similar issue like this? Currently, I am using EF 6.1.3.
Note: I used code-first for this, so it was not an existing database I am adding to.
The issue was that a new directory had been created for the site due to the domain name being changed. I knew the domain name had changed, but didn't realize the physical directory had changes. It was such a slight change I missed it when I was checking the application paths (an s was removed). So the problem was caused by pebkac (problem exists between keyboard and chair).
Try to set your Initializer to null in the constructor of your DbContext class.
Like this:
Database.SetInitializer<YourDbContext>(null);
ScottGu's Blog explains why this happens :
http://weblogs.asp.net/scottgu/using-ef-code-first-with-an-existing-database
Have you tried using this command instead of executing a script?
Update-Database -Force
If you have enabled auto migrations, this should pick up your code-first changes and deploy them. The force will allow columns which have data to be dropped etc.

Update-Database fails on production server

I've enabled migrations for my ASP.NET MVC project. Migrations work perfectly on localhost. However I get the following exception after deploying it to the server:
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
View Stack Trace
There are no pending migrations, though. Adding a new migration just creates empty Up() & Down()
What could be the reason it doesn't work on the server? I've tried deleting the migrations folder, re-enabling migrations, deleting the database, and let EF do it afresh. The tables get created, but I end up with that exception.
Update:
Another thing I noticed is, when I delete the migration folder but not the database, and enable migrations, it only adds a Configuration.cs file, when it's supposed to add another file too (initialcreate.cs)
This happens when you are doing tow different query on the same list of objects on the same time without using .toList
example :
you can create context and get a list of testObjects then edit one of this objects then save changes
var objectsList = context.testObjects.where(x=>x.whatever=true)
objectsList[0].whatever2="asd"
context.SaveChanges()
the above code will pass the compailer and it will fail while running, to solve this it should be as below
var objectsList = context.testObjects.where(x=>x.whatever=true).ToList()
objectsList[0].whatever2="asd"
context.SaveChanges()

EF Code first migrations not running after deploy to Azure

I have two folders for my migrations (AuthContext and UserProfileContext), each has their own migration and some custom sql to run afterwards for data migrations and whatnot.
This works fine when using package manager console. I
Restore from production
Run Update-Database -ConfigurationTypeName Migrations.Auth.Configuration
Run Update-Database -ConfigurationTypeName Migrations.UserProfile.Configuration
Then everything is very happy in the new database, migrations executed data shuffled where it needs to.
I tried to test out the migrations on publish piece by:
Restore production on dev database
Single connection string (all contexts use the same) pointed to dev database
Publish to azure web site
Checked the box for Apply Code First Migrations
Selected that single connection string
Okay it published fine; however, when I went to look at the database, nothing happened! It did not create the necessary tables, columns, or data moves.
TLDR; Code first migrations are not running after publish to Azure
Update 1
I've tried any combination of the below: only one single connection string so I'm guessing that's not the issue, and execute migrations is checked.
On publish the api runs but no database changes are made. I thought perhaps I needed to hit it first but I just get random errors when I try to use the api (which now of course relies on the new database setup), and the database is still not changed.
I've seen a couple references out there about needing to add something to my Startup class but I'm not sure how to proceed.
Update 2
I solved one issue by added "Persist Security Info=True" to my connection string. Now it actually connects to the database and calls my API; however, no migrations are running.
I attached debugger to Azure dev environment and stepped through... on my first database call it steps into the Configuration class for the Migration in question, then barfs and I can't track down the error.
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"Migrations\Auth";
ContextKey = "AuthContext";
}
Update 3
Okay, dug down and the first time it hits the database we're erroring. Yes this makes sense since the model has changed, but I have migrations in place, enabled, and checked! Again, it works fine when running "Update-Database" from package manager console, but not when using Execute Code First Migrations during publish to Azure
The model backing the 'AuthContext' context has changed since the
database was created. Consider using Code First Migrations to update
the database (http://go.microsoft.com/fwlink/?LinkId=238269).
Update 4
Okay I found the root issue here. VS is setting up the additional web.config attrib for databaseInitializer on only one of my database contexts, the one not mentioned is in fact hit first from my app.
So now I have to figure out how to get it to include multiple contexts, or, combine all of my stuff into a single context.
The answer to this post is not very detailed.
This article explains what I had to do to fix a similar problem to this:
https://blogs.msdn.microsoft.com/webdev/2014/04/08/ef-code-first-migrations-deployment-to-an-azure-cloud-service/
I'll roughly describe the steps I had to take below:
Step 1
Add your connection strings to your dbContexts, in my situation, they were both the same.
Step 2
Add this to your web.config
<appSettings>
<add key="MigrateDatabaseToLatestVersion" value="true"/>
</appSettings>
Step 3
And add this to the bottom of your global.asax.cs / Startup.cs(OWIN startup)
var configuration = new Migrations.Configuration();
var migrator = new DbMigrator(configuration);
migrator.Update();
Solved! To summarize the solution for posterity:
Enable Code First Migrations only enables them for one base connection string per checkbox checked, regardless of how many contexts have migrations against that base connection string. So in my case I broke out the two in question into two different connection strings.
Then I was hitting other errors and identified that if you're changing the base connection string to the model backing asp identity you need to include (one time publish) the additional flag base("AuthContext" , throwIfV1Schema: false)
For anyone who has this issue and may have overlooked the following: be sure to check that you have correctly set the connection string in your Web.config file and/or Application settings on Azure. This includes DefaultConnection and DefaultConnection_DatabasePublish.
In our case the former was correct but the latter contained the wrong database instance because it had been carried over from an App Service clone operation. Therefore the wrong database was being migrated.

Can I access a migrated EF database with "old" code?

If I have an EF6 Code First environment in need of a schema change, is it possible to configure it in such a way that I can apply the migration (via Update-Database -Script) before the code gets deployed?
I just ran a simple test with a console app building a DB with migration "Initial", taking a copy of the application at this point. I then modified the schema by adding a new property to my entity and added a "V2" migration and ran Update-Database. When trying to run the "old" code against this migrated DB, I get an InvalidOperationException "The model backing the context has changed since the database was created."
Is the Continuous Delivery type operation where you might want one server running new application code with others running old versions possible with EF code first?
can you modify old code ?
if yes disabling schema checking in old code is an option.
btw: Are you sure the added column is nullable or as a default value ?
to avoid surprises, you can also use a connection string that has read only rights on the schema to avoid data corruption.

EF6 + SQL Server CE + two contexts+ CodeFirst Migrations from code - Detect Pending Changes after Add-Migration

Entity Framework 6.0.2. .Net 4. I am trying to update SQL Server CE 4.0 database from code, so when a new version of the application is released, the database(s) are automatically upgraded.
There are two data contexts in the project and they are targeting two different databases. This is what I am doing to update one of them:
Private Sub UpdateDatabase(connectionString As String)
Dim config As DbMigrationsConfiguration(Of MainDBContext) = New DbMigrationsConfiguration(Of MainDBContext)()
config.TargetDatabase = New System.Data.Entity.Infrastructure.DbConnectionInfo(connectionString, "System.Data.SqlServerCe.4.0")
config.ContextKey = "MyProject.MainDBContext"
Dim migrator As DbMigrator = New DbMigrator(config)
migrator.Update()
End Sub
The message from the Update method is that there are pending changes so I have to either run Add-Migration or enable Automatic Migrations. However, Add-Migration has been run and when I do allow automatic migrations, Update tries to create tables which already are in the DB.
Running Update-Database works fine when called like this:
Update-Database -configuration MyProject.MigrationsMainDb.Configuration -Verbose
I checked that the connection string used in the UpdateDatabase function is same as the one in the config file (used by Update-Database). I also tried not setting the ContextKey property, but it made no difference.
Is there anything obvious that I am doing wrong? Why does the migrator thinks there are pending updates but Update-Database is fine...?
I made it working. I realized that instead of creating the "generic" configuration class I should create the configuration class which had been added to the project by Enable-Migrations command. So the code has been changed to the following:
Private Sub UpdateDatabase(connectionString As String)
Dim config As MigrationsMainDb.Configuration = New MigrationsMainDb.Configuration()
config.TargetDatabase = New System.Data.Entity.Infrastructure.DbConnectionInfo(connectionString, "System.Data.SqlServerCe.4.0")
Dim migrator As DbMigrator = New DbMigrator(config)
migrator.Update()
End Sub
And this change resulted in the configuration object having properties set up correctly. For example the MigrationsDirectory property, which was not set before to what it should be. This was probably the reason of the issue - the migrator not finding migrations (looking for them in wrong directory) and assuming that the whole model has to be applied to the DB.
After making this change, I still had a small glitch with a pending change. In Visual Studio a file looked like modified, with one extra (test) property in the class, but when I tried to remove the extra line, I got a message from VS like "edited on master", or something like that. I closed the file and reopened - the extra property disappeared. I guess it was something with git, checking out branches and VS not refreshing files properly? Not sure really. But once this line was no longer there and the modified code in place, the Update function started working fine.
Update now updates existing databases and successfully creates new ones. Great :)