简体   繁体   中英

Entity Framework: Multiple code first migrations and the configuration seed method

I'm adding a column to a table with Entity Framework Code First Migrations. I've read you can use the Seed method in configuration.cs and it will seed data when update-database is run. How does this work if you have multiple migrations? One migration might need to seed some data and another migration might need other data seeded. There is only one Seed method in the configuration file. How do you prevent Entity Framework from seeding the same data multiple times in the future when you add more migrations? Do you just delete the contents of the Seed method in the configuration file?

When Update-Database is run, the Seed method is passed the DbContext as the argument. You can do anything you'd like with the context, including querying the database to see what data is already there and making sure your Seed method is idempotent.

For instance, you might want to always make sure the database is always seeded with an administrator if none exist...

protected override void Seed(MyDbContext context)
{
    if (!context.Users.Any(u => u.Username == "administrator"))
    {
        var user = new User { Username = "administrator", PasswordHash = "hashed password" };
        context.Users.Add(user);
        context.SaveChanges();
    }
}

I store a variable for currentVersion in my database, and compare it with new version and do upgrade actions. It works like following codes. The UpgradeVersion() will do upgrade action if currenVersion is older than newVersion . If currentVersion is equal or newer than newVersion , the UpgradeVersion() does nothing.

   protected override void Seed(MyDbContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //

        UpgradeVersion(context, 100, null);
        UpgradeVersion(context, 101, (ver) => { /*do upgrade actions to version 101 */ });
        UpgradeVersion(context, 102, (ver) => { /*do upgrade actions to version 102 */ });
    }

    private void UpgradeVersion(MyDbContext context, int newVersion, Action<int> upgradeAction) {
        //  If newVersion > currentVersion, call upgradeAction(newVersion) and set currentVersion to newVersion
        //  Else, return directly and do nothing.

    }

I know this is a bit late but I came across this answer and was unsatisfied with it. After a bit of tinkering here's a alternative solution.

Run the following commands:

add-migration YourSchemaMigration
update-database
add-migration YourDataMigration

This should scaffold and apply your schema changes, then the second add-migration call should scaffold an empty migration for you. Instead of using the migration to add or remove fields or tables, open up a DbContext in there and start dropping data

public partial class YourDataMigration : DbMigration 
{
    public override void Up() 
    {
        // Importing from CSV
        using(db = new FooDbContext())
            ImportUtil.ImportFoos(db, "initial_foo_data.csv"));
    }

    public override void Down()
    {
        // Nothing!
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM