none
DbMigrationsConfiguration and pending migrations RRS feed

  • Question

  • Having the need to run the DB update only if there are any pending migrations I wrote the following code:

    internal sealed class Config : DbMigrationsConfiguration<MyContext>
        {
            private readonly bool _pendingMigrations;
            public Config()
            {
                AutomaticMigrationsEnabled = true;
                //AutomaticMigrationDataLossAllowed = true;
    
                DbMigrator migrator = new DbMigrator(this);
                _pendingMigrations = migrator.GetPendingMigrations().Any();
            }
    
            protected override void Seed(MyContext ctx)
            {
                //Exit if there aren't any pending migrations
                if (!_pendingMigrations) return;
    
                ctx.Comuni.AddOrUpdate(
                    new Town { ID = 1, Comune = "Acquaviva delle Fonti", Provincia = "BA", Cap = "70021", Belfiore = "A048" },
                    new Town { ID = 2, Comune = "Adelfia", Provincia = "BA", Cap = "70010", Belfiore = "A055" }
                    );
            }
        }

    However I get the following error:

    This is strange because I've been following this example:

    http://stackoverflow.com/questions/13510341/entity-framework-5-migrations-setting-up-an-initial-migration-and-single-seed-o

    • Edited by piedatt80 Saturday, April 19, 2014 8:17 AM error
    Saturday, April 19, 2014 8:14 AM

Answers

  • '...enable migration for the selected context, add a migration using add-migration command...'

    Actually I would prefer that the migration happens in a fully automatic mode. Therefore, I wrote like this:

    internal sealed class Config : DbMigrationsConfiguration<MyContext>
        {
            public Config()
            {
                AutomaticMigrationsEnabled = true;
                AutomaticMigrationDataLossAllowed = true;
    
            }
    
            protected override void Seed(MyContext ctx)
            {
                if (ctx.Comuni.Count() == 0)
                {
                    ctx.Comuni.AddOrUpdate(
                        new Town { ID = 1, Comune = "Acquaviva delle Fonti", Provincia = "BA", Cap = "70021", Belfiore = "A048" },
    • Marked as answer by piedatt80 Thursday, May 1, 2014 4:35 PM
    Sunday, April 27, 2014 3:30 PM

All replies

  • Hello,

    >>This is strange because I've been following this example

    How do you make your Config class? By using the enable-migrations PCM, if it is, this is very strange since I made a test with this scenario but working successfully, or it is that you create the Config class yourself since as far as I know if we use the PCM, the default name should Configuration and use var migrator = new DbMigrator(this); rather than DbMigrator migrator = new DbMigrator(this), I ask it because I reprocedure this error with second scenario.

    This is the tested config class which is generated by using PCM:

    internal sealed class Configuration : DbMigrationsConfiguration<S14Context>
    
        {
    
            private readonly bool _pendingMigrations;
    
            public Configuration()
    
            {
    
                this.AutomaticMigrationsEnabled = true;
    
                this.AutomaticMigrationDataLossAllowed = true;
    
    
                var migrator = new DbMigrator(this);
    
                _pendingMigrations = migrator.GetPendingMigrations().Any();
    
    
            }
    
    
            protected override void Seed(S14Context context)
    
            {
    
                if (!_pendingMigrations)
    
                    return;
    
    
                Blog b = new Blog() { BlogId = 1, Name = "1" };
    
    
                context.Blogs.Add(b);
    
    
                context.SaveChanges();
    
            }
    
        }

    For the error, you can set a breakpoint at the public Configuration() line and will find if we use the self-created config class, it will in a loop so that it will cause a stackoverall exception while if we use the config class generated by using PCM, it will go on successfully.

    So the DbMigrator should work with PCM, I think. You can have a try.

    If I misunderstand, please let me know.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Monday, April 21, 2014 3:25 AM
    Moderator
  • Unfortunately I have not yet managed to solve my problem:

    namespace DAL
    {  
        public class Qualification : IEntityWithId
        {
            public int ID { get; set; }
            public string Qualifica { get; set; }
    
            [Timestamp]
            public byte[] RowVersion { get; set; }
        }
        public class Cop : IEntityWithId
        {
            public int ID { get; set; }
            public string Matricola { get; set; }
            public string Cognome { get; set; }
            public string Nome { get; set; }
            public int? QualificaID { get; set; }
    
            [Timestamp]
            public byte[] RowVersion { get; set; }
            public virtual Qualification Qualifica { get; set; }
        }
        
        public class MyContext : DbContext
        {
            public MyContext()
            {
                Database.SetInitializer<MyContext>(new MigrateDatabaseToLatestVersion<MyContext, Config>());
            }
    
            public DbSet<Qualification> Qualifiche { get; set; }
            public DbSet<Cop> Agenti { get; set; }
            
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<Cop>()
                    //.HasRequired(q => q.Qualifica)
                    .HasOptional(q => q.Qualifica)
                    .WithMany()
                    .HasForeignKey(q => q.QualificaID)
                    .WillCascadeOnDelete(false);
    
                base.OnModelCreating(modelBuilder);
            }
        }
    }

    and

    namespace DAL
    {
        internal sealed class Config : DbMigrationsConfiguration<MyContext>
        {
            private readonly bool _pendingMigrations;
            public Config()
            {
                AutomaticMigrationsEnabled = true;
                AutomaticMigrationDataLossAllowed = true;
    
                var migrator = new DbMigrator(this);
                _pendingMigrations = migrator.GetPendingMigrations().Any();
            }
    
            protected override void Seed(MyContext ctx)
            {
                ctx.Qualifiche.AddOrUpdate(
                    new Qualification { ID = 1, Qualifica = "Agente" },
                    new Qualification { ID = 2, Qualifica = "Maresciallo" },
                    new Qualification { ID = 3, Qualifica = "S.Tenente" },
                    new Qualification { ID = 4, Qualifica = "Tenente" },
                    new Qualification { ID = 5, Qualifica = "Capitano" },
                    new Qualification { ID = 6, Qualifica = "Maggiore" },
                    new Qualification { ID = 7, Qualifica = "Tenente Colonnello" },
                    new Qualification { ID = 8, Qualifica = "Colonnello" }
                    );
            }
        }
    }

    I noticed that it generates an infinite loop between:

    Database.SetInitializer<MyContext>(new MigrateDatabaseToLatestVersion<MyContext, Config>());
    
    var migrator = new DbMigrator(this);
    Tuesday, April 22, 2014 9:10 AM
  • Okey, I found that I made a mistake that I forgot to add this line so I run it successfully:

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

    However, I think we do not need this line actually. From the link, I do not see that Jon Smith gave this context class and we do not know if it has this line.

    For the reason it generates an infinite loop, we can see the constructor of the DbMigrator class:

    public DbMigrator(DbMigrationsConfiguration configuration)
    
                : this(configuration, null)
    
            {
    
                Check.NotNull(configuration, "configuration");
    
                Check.NotNull(configuration.ContextType, "configuration.ContextType");
    
            }

    It will call its additional constructor:

    internal DbMigrator(DbMigrationsConfiguration configuration, DbContext usersContext)
    
                : base(null)
    
    {
    
    //…
    
    }

    In it, we can see that it will call the DisableInitializer method.

    DisableInitializer(_configuration.ContextType);

    It invokes constructor represented by the current instance:

    _setInitializerMethod
    
                    .MakeGenericMethod(contextType)
    
                    .Invoke(null, new object[] { null });

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Wednesday, April 23, 2014 9:12 AM
    Moderator
  • Thanks for the quick reply, but I still haven't figured out how I need to change my code to work correctly.
    Thursday, April 24, 2014 9:09 AM
  • Hello,

    Please comment out this line:

    Database.SetInitializer<S14Context>(new MigrateDatabaseToLatestVersion<S14Context, CF.Migrations.Configuration>());

    And enable migration for the selected context, add a migration using add-migration command, then use the update-database command to migrate the database and since we add a migration, it will detach that there is a migration is pending, so if (!_pendingMigrations) will return true and will execute the AddOrUpdate() method.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, April 24, 2014 10:05 AM
    Moderator
  • '...enable migration for the selected context, add a migration using add-migration command...'

    Actually I would prefer that the migration happens in a fully automatic mode. Therefore, I wrote like this:

    internal sealed class Config : DbMigrationsConfiguration<MyContext>
        {
            public Config()
            {
                AutomaticMigrationsEnabled = true;
                AutomaticMigrationDataLossAllowed = true;
    
            }
    
            protected override void Seed(MyContext ctx)
            {
                if (ctx.Comuni.Count() == 0)
                {
                    ctx.Comuni.AddOrUpdate(
                        new Town { ID = 1, Comune = "Acquaviva delle Fonti", Provincia = "BA", Cap = "70021", Belfiore = "A048" },
    • Marked as answer by piedatt80 Thursday, May 1, 2014 4:35 PM
    Sunday, April 27, 2014 3:30 PM
  • Any other suggestion?
    Wednesday, April 30, 2014 9:37 AM
  • Hello,

    Does this work for you?

      if (ctx.Comuni.Count() == 0)
    
                {
    
                    ctx.Comuni.AddOrUpdate(
    
                        new Town { ID = 1, Comune = "Acquaviva delle Fonti", Provincia = "BA", Cap = "70021", Belfiore = "A048" })
    
    }
    

    Or does it throw any exception, if it has, please share it with us.

    Thanks&Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, April 30, 2014 9:57 AM
    Moderator
  • The solution I posted works fine. Maybe it is not exactly elegant, but it works.
    Wednesday, April 30, 2014 2:43 PM