Reputation: 87220
I'm getting a little confused by the different approaches to migrations in Entity Framework 6.1.1
Up until now it was my understanding that I have to always run Update-Database
in order to update the schema so that it reflects my newly added models. But now I just managed to create a POCO model, add a DbSet<Foo> Foos {get;set;}
to my ApplicationDbContext
, re-build the application and everything magically works.
Previously I remember having to run Enable-Migrations
and then turn on the automatic migrations and always call Update-Database
to migrate, but it seems this is not necessary after all?
Just to clarify, I'm using the ASP.NET Web Application template with MVC and Internet authentication (just the basic user accounts that are generated by the scaffold).
There seem to be just so many different approaches to migrations and so many tutorials, where every one of them does it a bit differently, that I'm not sure which approach is actually the correct one. It feels to me that I'm mixing together things that could be kept separate. Most of the resources I found online are also referencing different versions of EF and ASP.NET MVC.
What are the steps needed to be able to generate my database schema based on my POCO models? Is there an easy way to just re-create and re-seed the database as needed automatically, or do I have to keep using Update-Database
after that?
I'm using Visual Studio 2013 Ultimate if that's of any relevance.
Upvotes: 1
Views: 1144
Reputation: 14640
Up until now it was my understanding that I have to always run Update-Database in order to update the schema so that it reflects my newly added models.
You can run the migration from Package Manager Console, initializer or code.
PM> Update-Database
Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppContext, Configuration>());
or DbMigrator(new Configuration()).Update()
new DbMigrator(new Configuration()).Update();
But now I just managed to create a POCO model, add a DbSet Foos {get;set;} to my ApplicationDbContext, re-build the application and everything magically works.
If you have exiting database and there is a new changes in your model, e.g. by adding a new DbSet<T>
or just adding a new property, without setting any initializer / migration (in the code or in the config), you should get error like.
The model backing the 'AppContext' context has changed since the database was created. Consider using Code First Migrations to update the database.
You probably have set somewhere to use MigrateDatabaseToLatestVersion
and set AutomaticMigrationsEnabled = true;
.
and then turn on the automatic migrations and always call Update-Database to migrate, but it seems this is not necessary after all?
Yes, it's not necessary anymore once you have enabled automatic migration.
What are the steps needed to be able to generate my database schema based on my POCO models?
If you want to maintain the database version manually:
DbMigrationsConfiguration<TContext>
or just use PMC PM> Enable-Migrations
DbMigration
manually by writing the sql query for each version or just use PMC PM> Add-Migration MigrationNameForVersioning
AutomaticMigrationsEnabled = false
MigrateDatabaseToLatestVersion
If you just want to automatically update the database without creating each migration version manually.
DbMigrationsConfiguration<TContext>
or just use PMC PM> Enable-Migrations
AutomaticMigrationsEnabled = true
MigrateDatabaseToLatestVersion
Code
internal sealed class Configuration : DbMigrationsConfiguration<AppContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "AppContext"; // don't forget to match this key if create the class manually
}
protected override void Seed(AppContext context)
{
}
}
Usage
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<AppContext, Configuration>());
More
Upvotes: 1
Reputation: 2907
I believe you have multiple questions here, so I'll address them as best I can.
First:
I just managed to create a POCO model, add a DbSet Foos {get;set;} to my ApplicationDbContext, re-build the application and everything magically works.
It seems as if you have Automatic Code First Migrations turned on for your project. From the link provided, it seems that the automatic migrations are not enabled by default, so something must have changed on your end either by running the command, or by using custom code (shown later)
If you were to run the application again you would get an InvalidOperationException stating The model backing the 'BlogContext' context has changed since the database was created. Consider using Code First Migrations to update the database ( http://go.microsoft.com/fwlink/?LinkId=238269).
As the exception suggests, it’s time to start using Code First Migrations. Because we want to use automatic migrations we’re going to specify the –EnableAutomaticMigrations switch.
Run the Enable-Migrations –EnableAutomaticMigrations command in Package Manager Console
Next:
What are the steps needed to be able to generate my database schema based on my POCO models?
Well, you have several options here; EF Automatic Migrations, EF 'Standard' Migrations, third party library migrations (FluentMigrator). This would be to broad of a question by itself. But any and all options are valid, it just depends on your needs. I'm currently using EF Automatic Migrations for a personal project and FluentMigrator at work.
Finally:
Is there an easy way to just re-create and re-seed the database as needed automatically, or do I have to keep using Update-Database after that?
What are you trying to do here is the important question. I'm pretty sure you wouldn't want to drop and recreate / reseed the database in production (although that is possible).
You'll probably want to use some sort of DBInitializer to fit your needs. Here is a tutorial I used when researching this a few months back. You have 3 default options (CreateDatabaseIfNotExists, DropCreateDatabaseIfModelChanges, DropCreateDatabaseAlways), and of course the ability to customize your own.
Another option available is to write a custom DbMigrationsConfiguration . I can't find the article where I read about that, but here is some sample code. In this code, I have my DBContext initializing using my custom configuration class in which I have turned on EF Automatic Migrations and populate my database with some default data.
DBContext
public ApplicationDBContext()
: base("DefaultConnection")
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDBContext, IBCF.Core.Migrations.Configuration>());
}
Configuration
internal sealed class Configuration : DbMigrationsConfiguration<IBCF.Core.ApplicationDBContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(IBCF.Core.ApplicationDBContext context)
{
//Initialize managers
var userManager = new UserManager<User>(new UserStore<User>(context));
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
if(userManager.FindByEmail("[email protected]") == null)
{
//Add default system roles
roleManager.Create(new IdentityRole("Superuser"));
roleManager.Create(new IdentityRole("User"));
//Add default system users
var superuser1 = new User() { FirstName = "John", LastName = "Doe", Email = "[email protected]", UserName = "[email protected]" };
if (userManager.Create(superuser1, "P@ssword123").Succeeded)
{
userManager.AddToRole(superuser1.Id, "Superuser");
}
}
context.SaveChanges();
}
}
Upvotes: 1