How to seed data when using Model First approach?
Asked Answered
M

3

20

So I am learning MVC3 and EF4. I tried the code first method but it was too confusing for me.. I can create the classes no problem, but the hard part comes when dealing with foreign keys and the relationships between each other.

But I've gone with model first. This way I can visually design it and see where the relationships are.

After my model is create, it creates a SQL for me which I execute against my SQL Express database. Done, and done.

Now I want data in my tables. Of course I can just add them in using server explorer, but most likely I will be making changes to my model as I go along. And keep updating the database. So I can't keep manually entering data. I know if you use code first you can derive the DropCreateDatabaseIfModelChanges and override the seed method.

However how do I do this with model first approach? I have the following code:

 public class DatabaseInitializer : IDatabaseInitializer<BettingContext> {
    public void InitializeDatabase(BettingContext context) {
        var teams = new List<Team> {
            new Team { Name="Toronto Maple Leafs", League="NHL"},
            new Team { Name="Boston Bruins", League="NHL"},
            new Team { Name="Vancouver Canucks", League="NHL"},
            new Team { Name="Nashville Predators", League="NHL"},
            new Team { Name="Montreal Canadiens", League="NHL"},
        };
    }
}

Of course and in my global file:

protected void Application_Start()
{
    Database.SetInitializer<BettingContext>(new DatabaseInitializer());
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

so now what? How do I tell it to run the method? What am I doing wrong?

Mardis answered 15/5, 2011 at 2:37 Comment(0)
O
6

You can have something like this:

public class MySeedData : DropCreateDatabaseIfModelChanges<YourDataBaseContextClass>
{
    protected override void Seed(YourDataBaseContextClass context)
    {  
       // Create objects here and add them to your context DBSets...

    }
}

public class YourDataBaseContextClass : DbContext
{


}

Then, within Application_Start() you call:

Database.SetInitializer(new MySeedData());

In your case, you could try creating DbSets (using your model first classes) manually and try to plug it using the code above. It's kind of a mix of Model First + Code First.

public class FourthCoffeeWebContext : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
}

Adding to this: CreateDatabaseIfNotExists<(Of <(<'TContext>)>)>

Oppenheimer answered 15/5, 2011 at 2:48 Comment(3)
Would this work even if I am using Model First approach instead of Code First?Mardis
How can it know if the model changed? It has no metadata table.Mardis
@masfenix, any way to init database on model-first? did you find a solution? I tried the above and the db is not inited.Arroba
P
13

Model first is significantly different from Code First as you actually generate the database from the model as you're working on it. You get the SQL to create the database and run it manually, therefore I found it logical to keep next to this a 2nd SQL script with my seed data.

If I make changes to the model, The SQL script is updated and I of course need to review my seed SQL script (which is conveniently located right next to my Database creation script) I just run 1 after the other.

This approach has been working fine so far and doesn't create the confusion of 'where is this data loader and how does it identify an empty database'. (I can also include both these SQL scripts in my Setup project for my custom action to create the database with seed data.)

Perigee answered 11/5, 2012 at 11:17 Comment(0)
O
6

You can have something like this:

public class MySeedData : DropCreateDatabaseIfModelChanges<YourDataBaseContextClass>
{
    protected override void Seed(YourDataBaseContextClass context)
    {  
       // Create objects here and add them to your context DBSets...

    }
}

public class YourDataBaseContextClass : DbContext
{


}

Then, within Application_Start() you call:

Database.SetInitializer(new MySeedData());

In your case, you could try creating DbSets (using your model first classes) manually and try to plug it using the code above. It's kind of a mix of Model First + Code First.

public class FourthCoffeeWebContext : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
}

Adding to this: CreateDatabaseIfNotExists<(Of <(<'TContext>)>)>

Oppenheimer answered 15/5, 2011 at 2:48 Comment(3)
Would this work even if I am using Model First approach instead of Code First?Mardis
How can it know if the model changed? It has no metadata table.Mardis
@masfenix, any way to init database on model-first? did you find a solution? I tried the above and the db is not inited.Arroba
H
0

I use a Seeding Controller similar to the following:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyProject.Models;

namespace MyProject.Controllers
{
    public class SeedController : Controller
    {
        public string Index()
        {
            ContactDBContext db = new Models.ContactDBContext();

            Person person = new Person();
            person.FullName = "Mr Test";
            person.Notes = "It's me!";
            db.People.Add(person);
            db.SaveChanges();
            return "Seeding complete.";
        }
    }
}

Then after you have recreated your database from the Model Entity diagram simply navigate to the "/Seed" url of your website and it will repopulate with your seed data.

Hypnoanalysis answered 13/8, 2016 at 12:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.