Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MigrateDatabaseToLatestVersion no running Seed() method

I'm trying to automatically generate my database if it doesn't exists and run the Seed() method to populate the data. In my Database Context constructor I have this:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDBContext, Configuration>());

This works great, my database is automatically created with all the tables as I want, but it seems like the Seed() method is not being called, my database is empty. This is my class:

internal sealed class Configuration : DbMigrationsConfiguration<Context.MyDBContext>
{

    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(Context.MyDBContext context)
    {
        context.Users.AddOrUpdate(
            new Entities.User() { Email = "[email protected]", Password = "", Language = "en", CreatedDate = DateTime.Now }
        );

        base.Seed(context);
    }
}

When I run Update-Database in the Nuget console the data is populated after database creation, but with MigrateDatabaseToLatestVersion the Seed() method is not called.

What can be happening? I tried manually running migrations as taken from here:

var configuration = new MyDbContextConfiguration();
configuration.TargetDatabase = new DbConnectionInfo(
    database.ConnectionString, database.ProviderName);

var migrator = new DbMigrator(configuration);
migrator.Update();

But also doesn't work.


EDIT:

Ok, after some more testing I found that the Seed() method runs but only when the database already exists, that is, on the first run when the database is created for the first time the Seed() method is not executed, but when I run my app the second time Seed() get's executed. I also had to add context.SaveChanges() in order for it to work (thanks to @DavidG in the comments):

protected override void Seed(Context.MyDBContext context)
    {
        context.Users.AddOrUpdate(
            new Entities.User() { Email = "[email protected]", Password = "", Language = "en", CreatedDate = DateTime.Now }
        );

        context.SaveChanges();
        base.Seed(context);
    }

So maybe I can manually call Seed() inside Configuration() and do some checking to avoid adding duplicating data or modifying data that already exists.

like image 893
Andres Avatar asked Mar 15 '16 23:03

Andres


1 Answers

I ended up with this Configuration class:

public class Configuration : DbMigrationsConfiguration<Context.MyDBContext>
    {
        private readonly bool _pendingMigrations;

        public Configuration()
        {
            AutomaticMigrationsEnabled = true;

            // Check if there are migrations pending to run, this can happen if database doesn't exists or if there was any
            //  change in the schema
            var migrator = new DbMigrator(this);
            _pendingMigrations = migrator.GetPendingMigrations().Any();

            // If there are pending migrations run migrator.Update() to create/update the database then run the Seed() method to populate
            //  the data if necessary
            if (_pendingMigrations)
            {
                migrator.Update();
                Seed(new Context.MyDBContext());
            }
        }

        protected override void Seed(Context.MyDBContext context)
        {
            // Microsoft comment says "This method will be called after migrating to the latest version."
            // However my testing shows that it is called every time the software starts

            // Run whatever you like here

            // Apply changes to database
            context.SaveChanges();
            base.Seed(context);
        }
    }

So on this way the Seed() method is called when the database is created and also when there are pending migrations.

This is my MyDBContext class:

public class MyDBContext: DbContext
{
    public MyDBContext() : base(AppSettings.DBConnectionString)
    {
    }

    public static MyDBContext Create()
    {
        return new MyDBContext();
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Entries> Entries { get; set; }
}
like image 144
Andres Avatar answered Sep 18 '22 15:09

Andres