44

How do I handle situations in which I need pre-existing data before the app is started or right after the database is generated. For example, I have a list of countries in which I'd like to load into the database after code-first generates it. How do I do this?

App is structured as follows:

Repository > Service > WebMVC

The xml is in the WebMVC project.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
Shawn Mclean
  • 56,733
  • 95
  • 279
  • 406

3 Answers3

67

You create custom initializer, which inherits from DropCreateDatabaseIfModelChanges or DropCreateDatabaseAlways interface. Like:

public class EntitiesContextInitializer : DropCreateDatabaseIfModelChanges<-YourDbContext->

And then you overwrite Seed method like:

protected override void Seed(YourDbContext context)

Whole example might look like:

public class EntitiesContextInitializer : DropCreateDatabaseIfModelChanges<EntitiesContext>
{
    protected override void Seed(EntitiesContext context)
    {
        List<Role> roles = new List<Role>
        {
            new Role {Id=1, Title="Admin"},
            new Role {Id=2, Title="ProjectManager"},
            new Role {Id=3, Title="Developer"}
        };

        // add data into context and save to db
        foreach (Role r in roles)
        {
            context.Roles.Add(r);
        }
        context.SaveChanges();

    }
}

Edit: After setting this up, you have to set up Initializer too, as Ladislav Mrnka mentioned.

Database.SetInitializer(new EntitiesContextInitializer());

ie.: in Global.asax:

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

Don't forget to add using System.Data.Entity; .....

t3dodson
  • 3,949
  • 2
  • 29
  • 40
Damb
  • 14,410
  • 6
  • 47
  • 49
  • This will only create list of roles. You must add them to the context and save changes. – Ladislav Mrnka Apr 13 '11 at 21:35
  • @Dampe Can I use the Database.SetInitializer in the webUI project or does it have to be where I create the DbContext? – Shawn Mclean Apr 13 '11 at 22:17
  • @Lol coder: You can add it into Global.asax file into `Application_Start` method. You will need to add Using.System.Data.Entity; – Damb Apr 13 '11 at 22:21
  • 2
    For some reason it executes the Database.SetInitializer method, but it does not execute the Seed method. I set break points in it and nothing happened. – Shawn Mclean Apr 14 '11 at 01:58
  • I don't know what could be wrong. It works for me. Maybe your database is already filled and you are using `DropCreateDatabaseIfModelChanges`. Try to manually delete the database in SQL Management Studio (or tool you use). And run the app again. It should be fired when there is no database prepared. – Damb Apr 14 '11 at 10:58
  • 3
    Not a bad idea to call `base.Seed()` at the end of this method. – H H May 27 '13 at 12:33
  • Small note, you don't need to call `context.SaveChanges();` in `Seed()`, even if you skip `base.Seed()` it saves automatically. – Full_Int Aug 31 '13 at 16:33
  • There is no need to call base.Seed() it does nothing. Also, as Full_Int has said above there is no need to call SaveChanges(). This happens automatically after seeding. – Anthony Nichols Jan 17 '16 at 05:10
  • I guess there were some changes in EF in the 5 years that have passed since this answer was written :) It's nice to see they were cutting unnecessary (always repeating) pieces like context.SaveChanges() – Damb Jan 17 '16 at 13:05
11

You must create custom database initializer derived for example from DropCreateDatabaseIfModelChanges and fill data in overriden Seed method. Then you must use Database.SetInitializer to set your new initializer when application starts. Here is example (from CTP5) used to create custom index in the database.

Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • because I can only use the file access code from the web front end, is there a way for me to call the initializer or pass up the data instead? – Shawn Mclean Apr 13 '11 at 22:16
  • You can wrap initialization in custom code and pass data from web app to that code which will in turn pass data to a new instance of your initializer. – Ladislav Mrnka Apr 13 '11 at 22:29
1

For an example see the new MVC / Entity Framework tutorial series at http://www.asp.net/entity-framework/tutorials#Using%20MVC Both #1 and #4 show initializer classes.

tdykstra
  • 5,880
  • 2
  • 23
  • 20