Wai Yan Hein
Wai Yan Hein

Reputation: 14771

Seeding not working in Entity Framework Code First Approach

I am developing a .Net project. I am using entity framework code first approach to interact with database. I am seeding some mock data to my database during development. But seeding is not working. I followed this link - http://www.entityframeworktutorial.net/code-first/seed-database-in-code-first.aspx.

This is my ContextInitializer class

public class ContextInitializer : System.Data.Entity.CreateDatabaseIfNotExists<StoreContext>
    {

        protected override void Seed(StoreContext context)
        {
            IList<Brand> brands = new List<Brand>();
            brands.Add(new Brand { Name = "Giordano" ,TotalSale = 1 });
            brands.Add(new Brand { Name = "Nike" , TotalSale = 3 });

            foreach(Brand brand in brands)
            {
                context.Brands.Add(brand);
            }
            base.Seed(context);
            context.SaveChanges();

        }
    }

This is my context class

public class StoreContext : DbContext,IDisposable
    {
        public StoreContext():base("DefaultConnection")
        {
            Database.SetInitializer(new ContextInitializer());
        }

        public virtual DbSet<Category> Categories { get; set; }
        public virtual DbSet<Brand> Brands { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
   }

This is my brand class

public class Brand
    {
        public int Id { get; set; }
        [Required]
        [MaxLength(40)]
        public string Name { get; set; }
        public int TotalSale { get; set; }
    }

I searched solutions online and I followed instructions. I run context.SaveChanges as well. But it is not seeding data to database. Why it is not working?

Upvotes: 4

Views: 4108

Answers (3)

Bassam Alugili
Bassam Alugili

Reputation: 16983

You are taking the wrong initializer, CreateDatabaseIfNotExists is called only if the database not exists!

You can use for example DropCreateDatabaseIfModelChanges:

Solution 1)

public class ContextInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<StoreContext>
{

You have to take care with this approach, it !!!removes!!! all existing data.

Solution 2)

Create a custom DbMigrationsConfiguration:

public class Configuration : DbMigrationsConfiguration<StoreContext>
{
    public Configuration()
    {
        // Take here! read about this property!
        this.AutomaticMigrationDataLossAllowed = true;
        this.AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(StoreContext context)
    {
        IList<Brand> brands = new List<Brand>();
        brands.Add(new Brand { Name = "Giordano", TotalSale = 1 });
        brands.Add(new Brand { Name = "Nike", TotalSale = 3 });

        foreach (Brand brand in brands)
        {
            context.Brands.AddOrUpdate(m => m.Name, brand);
        }
        base.Seed(context);
        context.SaveChanges();
    }
}

In this way you can called( !!Before you create the DbContext or in the DbContext constructor!!):

// You can put me also in DbContext constuctor     
Database.SetInitializer(new MigrateDatabaseToLatestVersion<StoreContext , Yournamespace.Migrations.Configuration>("DefaultConnection"));

Notes:

  • DbMigrationsConfiguration need to know about the connection string you can provide this info in the constructor or from outside.
  • In Your DbMigrationsConfiguration you can configure also:
    • MigrationsNamespace
    • MigrationsAssembly
    • MigrationsDirectory
    • TargetDatabase

If you leave everything default as in my example then you do not have to change anything!

Upvotes: 4

Abdul Hadi
Abdul Hadi

Reputation: 1228

Your code is working if you delete your existing database and the EF will create and seeding the data

Or

You can use DbMigrationsConfiguration insted of CreateDatabaseIfNotExists and change your code as follow:

First you have to delete the existing database

ContextInitializer class

public class ContextInitializer : System.Data.Entity.Migrations.DbMigrationsConfiguration<StoreContext>
{
    public ContextInitializer()
    {
        this.AutomaticMigrationDataLossAllowed = true;
        this.AutomaticMigrationsEnabled = true;
    }
    protected override void Seed(StoreContext context)
    {
        IList<Brand> brands = new List<Brand>();
        brands.Add(new Brand { Name = "Giordano", TotalSale = 1 });
        brands.Add(new Brand { Name = "Nike", TotalSale = 3 });

        foreach (Brand brand in brands)
        {
            context.Brands.AddOrUpdate(m => m.Name, brand);
        }
        base.Seed(context);
        context.SaveChanges();

    }
}

StoreContext

public class StoreContext : DbContext, IDisposable
    {
        public StoreContext() : base("DefaultConnection")
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<StoreContext, ContextInitializer>());
            //  Database.SetInitializer(new ContextInitializer());
        }

        public virtual DbSet<Category> Categories { get; set; }
        public virtual DbSet<Brand> Brands { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
    }

Then any change in your seed will automatically reflected to your database

Upvotes: 0

Erik Philips
Erik Philips

Reputation: 54618

Setting the Initializer for a Database has to happen BEFORE the context is ever created so...

    public StoreContext():base("DefaultConnection")
    {
        Database.SetInitializer(new ContextInitializer());
    }

is much to late. If you made it static, then it could work:

    static StoreContext()
    {
        Database.SetInitializer(new ContextInitializer());
    }

Upvotes: 1

Related Questions