How can I get my database to seed using Entity Framework CodeFirst?
Solution 1:
This is what my DbContext classes all look like and they seed just fine:
public class MyDbContext : DbContext
{
public DbSet<MyClass> MyClasses { get; set; }
protected override void OnModelCreating (DbModelBuilder modelBuilder)
{
base.OnModelCreating (modelBuilder);
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention> ();
// Add any configuration or mapping stuff here
}
public void Seed (MyDbContext Context)
{
#if DEBUG
// Create my debug (testing) objects here
var TestMyClass = new MyClass () { ... };
Context.MyClasses.Add (TestMyClass);
#endif
// Normal seeding goes here
Context.SaveChanges ();
}
public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<MyDbContext>
{
protected override void Seed (MyDbContext context)
{
context.Seed (context);
base.Seed (context);
}
}
public class CreateInitializer : CreateDatabaseIfNotExists<MyDbContext>
{
protected override void Seed (MyDbContext context)
{
context.Seed (context);
base.Seed (context);
}
}
static MyDbContext ()
{
#if DEBUG
Database.SetInitializer<MyDbContext> (new DropCreateIfChangeInitializer ());
#else
Database.SetInitializer<MyDbContext> (new CreateInitializer ());
#endif
}
}
I have used this pattern a few times and it has worked out very well for me.
Solution 2:
My Seed
method was not invoked even with proper call to Database.SetInitializer
in Application_Start
... The reason for it was really simple: initializer may not be invoked at all if you don't yet have any code that actually uses database context.
Solution 3:
This is my sad little tale.
First, lessons learned:
- The seed method won't be called until the context is used.
- The Global.asax.cs won't hit a breakpoint on first run bc it runs before the debugger is attached. To hit a breakpoint on Global.asax.cs, you have can add some white space to Web.config and hit a page; then it will get hit.
- If there are VS connections to the db, the seeding won't happen. The app will throw an error.
So, to avoid the sadness:
- Disconnect your VS connection.
- Switch the base class DropCreateDatabaseAlways for one go.
- Hit a page that uses the context.
Now, the sadness:
- I had my custom Initializer class in my Global.asax.cs file. I had a break point on my Initializer Seed method; I started the application and the method never got hit. :(
- I point a break point in my Database.SetInitializer call in Application_Start. That never got hit. :(
- I realized that I had no db schema changes, so then I changed DropCreateDatabaseIfModelChanges to DropCreateDatabaseAlways. Still, nothing. :(
- I finally went to a page that uses the context, and it worked. :/