Search code examples
entity-frameworkasp.net-mvc-3frameworksentitycode-first

How can I get my database to seed using Entity Framework CodeFirst?


The database is created successfully (as are the tables) but is not seeded. I have spent several hours and read tons of articles but have not been able to get it. Any suggestions?

On a side note, is it possible to call the initializer without having a reference to my DatabaseContext in the client?

I have included all the relevant code I could think of. If anything else would be helpful, please let me know.

Things I've Tried:

  1. I deleted my connection string (since it defaults to sqlexpress anyways, just the name changed)
  2. I changed DropCreateDatabaseIfModelChanges to DropCreateDatabaseAlways, still the same.

Edit: The really weird thing is it worked once, but I have no idea how or why it broke again. I am assuming connection strings, but who knows.

DatabaseInitializer.cs

public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seeding data here
    context.SaveChanges();
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Random mapping code
  }

  public DbSet<Entity1> Entities1 { get; set; }
  public DbSet<Entity2> Entities2 { get; set; }

}

Global.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer<DatabaseContext>(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

Client web.config

<connectionStrings>
  <add name="DatabaseContext" connectionString="data source=.\SQLEXPRESS;Database=Database;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>

SOLUTION

For the sake of documentation, I am sharing my solution here. Navigating all the comments would be a pain anyways. In the end I had DatabaseInitializer and DatabaseContext in separate classes. I don't really understand while these tiny changes fixed it, but here it is.

DatabaseInitializer.cs

public class DatabaseInitializer : CreateDatabaseIfNotExists<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seed code here
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  public DatabaseContext() : base("MyDatabase") { }

  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Code here
  }

  public DbSet<Entity> Entities { get; set; }
  // Other DbSets
}

Global.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

Solution

  • 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.