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:
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>
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);
}
Database. EnsureCreated() to create a new database containing the seed data, for example for a test database or when using the in-memory provider or any non-relational database. Note that if the database already exists, EnsureCreated() will neither update the schema nor seed data in the database.
Seed Data in Entity Framework Core So as soon as we execute our migration files to create and configure the database, we want to populate it with some initial data. This action is called Data Seeding. So, we are using the HasData method to inform EF Core about the data it has to seed.
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.
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.
This is my sad little tale.
First, lessons learned:
So, to avoid the sadness:
Now, the sadness:
You can call update-database
to manually run the seed method inside the Configuration
class. This requires enable-migrations
to be on as well.
PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending code-based migrations.
Running Seed method.
internal sealed class Configuration : DbMigrationsConfiguration<ProjectManager.Data.Database.ProjectDb>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(ProjectManager.Data.Database.ProjectDb context)
{
context.Status.AddOrUpdate(
new Status() { Id = 1, Text = "New" },
new Status() { Id = 2, Text = "Working" },
new Status() { Id = 3, Text = "Completed" },
new Status() { Id = 4, Text = "Skipped" }
);
}
}
The following change in the Global.asax file worked for me:
Old Code:
protected void Application_Start()
{
Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>());
...
}
New Code:
protected void Application_Start()
{
Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>());
Database.SetInitializer(new Initializer());
...
}
I too have had difficulty getting Seed() to be invoked. And I do appreciate all the helpful suggestions above and have had some luck using DropCreateDatabaseAlways ... but not ALWAYS!!
Most recently, I added the following line of code in the the constructor of my Repository to good effect:
public CatalogRepository()
{
_formCatalog.FormDescriptors.GetType();
}
It was sufficient to trigger the Seed() getting invoked. If you've tried everything above this answer and still no luck, give it a try. Good luck this was really a time consuming experience.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With