实体框架迁移 - 支持与加移民一起AutoMigrations(Entity Framework M

2019-07-29 10:51发布

我使用实体框架4.3迁移在我的项目。 我想用自动迁移,这样,当我进行修改我的域对象和我的上下文类,当我运行的项目我的数据库自动更新。 我有这个迄今为止的工作。

我也想用一些额外的迁移,除了自动迁移,我想申请当我运行的应用程序来自动跳转到最新版本(基于我加入迁移)。

为了做到这一点,我已经把这个在Global.asax文件...

Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Core.Migrations.Configuration>());

现在这个工作,但我这样做时,它基于我的域对象不再自动更新数据库。

我希望能够彻底删除数据库,然后运行该应用程序,并拥有所有的自动迁移运行,然后让我明确的迁移运行,使数据库的最新版本。

我知道我已经在以前的项目这方面的工作,但我不知道我在做什么错在这种情况下。

谢谢

Answer 1:

你需要通过具有AutomaticMigrationsEnabled设置为true在构造函数中的配置。 像这样的东西应该有所帮助:


Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, MyConfiguration>());

与MyConfiguration是这样的:

 public class MyConfiguration : Core.Migrations.Configuration { public MyConfiguration { this.AutomaticMigrationsEnabled = true; } } 

免责声明:在刚刚砍死这一点,所以小的调整可能需要得到这个编译

编辑:

只是EF 4.3.1检查和代码是这样的初始化:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<DataContext, MyConfiguration>());

这对于配置类:

public class MyConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<DataContext>
{
    public MyConfiguration()
    {
        this.AutomaticMigrationsEnabled = true;
    }
}


Answer 2:

敲打我对这个的头几个小时后,我终于想出了创建数据库,如果必要升级,如果过时的解决方案。 我们使用库服务器这种技术专业,以方便安装在第一时间或升级以前的版本。

private static void InitializeDataStore()
{
  System.Data.Entity.Database.SetInitializer(new System.Data.Entity.MigrateDatabaseToLatestVersion<GalleryDb, GalleryDbMigrationConfiguration>());

  var configuration = new GalleryDbMigrationConfiguration();
  var migrator = new System.Data.Entity.Migrations.DbMigrator(configuration);
  if (migrator.GetPendingMigrations().Any())
  {
    migrator.Update();
  }
}

public sealed class GalleryDbMigrationConfiguration : DbMigrationsConfiguration<GalleryDb>
{
  protected override void Seed(GalleryDb ctx)
  {
    MigrateController.ApplyDbUpdates();
  }
}

我写了一个博客帖子有更多的一些细节: 使用实体框架代码首先迁移到自动创建和自动更新的应用程序



Answer 3:

这是我目前的解决方案,这我并不完全满意。

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

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

    var context = new KCSoccerDataContext();
    var initializeDomain = new CreateDatabaseIfNotExists<KCSoccerDataContext>();
    var initializeMigrations = new MigrateDatabaseToLatestVersion<KCSoccerDataContext, Core.Migrations.Configuration>();

    initializeDomain.InitializeDatabase(context);
    initializeMigrations.InitializeDatabase(context);

}

实际上,我创建了两个不同的初始化。 首先,使用CreateDatabaseIfNotExists,succcessfully经过,并创建基于我的域对象表。 第二,使用MigrateDatabaseToLatestVersion,执行所有我明确的迁移。

我不喜欢它,因为自动迁移基本上禁用。 因此,为了添加或更改我的域模型,我必须完全删除该数据库并重新创建它。 一旦我感动应用到生产这是不能接受的。



Answer 4:

你只需要做的

    private static void InitializeDataStore()
    {
        System.Data.Entity.Database.SetInitializer(new System.Data.Entity.MigrateDatabaseToLatestVersion<GalleryDb, GalleryDbMigrationConfiguration>());
        System.Data.Entity.Database.Initialize(false);
    }


Answer 5:

如果您的应用程序包含Startup.cs类,你可以使用DbMigrator类如下转到您的App_Start文件夹,打开Startup.Auth粘贴ConfigureAuth方法内部的代码行

var configuration = new Migrations.Configuration();
        var dbmigrator = new DbMigrator(configuration);
        dbmigrator.Update();

注意:记住使用System.Data.Entity.Migrations使用此namespace-;

这样做是更新您的数据库,以最新版本的随时应用程序启动



Answer 6:

同样的解决方案罗杰做的,但使用上的DbContext的静态构造函数。 下面的完整代码....这允许初始化代码居住类本身,而且是自调用在DataDbContext类的第一个实例。

public partial class DataDbContext : DbContext
{
    public DataDbContext()
        : base("name=DefaultConnection")
    {
    }

    static DataDbContext() // This is an enhancement to Roger's answer
    {
        Database.SetInitializer(new DataDbInitializer()); 

        var configuration = new DataDbConfiguration();
        var migrator = new DbMigrator(configuration);

        if (migrator.GetPendingMigrations().Any())
            migrator.Update();
    }

    // DbSet's
    public DbSet<CountryRegion> CountryRegion { get; set; }
    // bla bla bla.....

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

        Configuration.ProxyCreationEnabled = false;
        Configuration.LazyLoadingEnabled = false;
        //Configuration.ValidateOnSaveEnabled = false; 

        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly()); // Discover and apply all EntityTypeConfiguration<TEntity> of this assembly, it will discover (*)
    }

}

internal sealed class DataDbInitializer : MigrateDatabaseToLatestVersion<DataDbContext, DataDbConfiguration>
{
}


internal sealed class DataDbConfiguration : DbMigrationsConfiguration<DataDbContext>
{
    public DataDbConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }

    protected override void Seed(DataDbContext context)
    {
        DataSeedInitializer.Seed(context); 
        base.Seed(context);
    }
}

internal static class DataSeedInitializer
{
    public static void Seed(DataDbContext context)
    {
        SeedCountryRegion.Seed(context);
        // bla bla bla.....

        context.SaveChanges();
    }
}

internal static class SeedCountryRegion
{
    public static void Seed(DataDbContext context)
    {
        context.CountryRegion.AddOrUpdate(countryRegion => countryRegion.Id,

            new CountryRegion { Id = "AF", Name = "Afghanistan" },
            new CountryRegion { Id = "AL", Name = "Albania" },
            // bla bla bla.....

            new CountryRegion { Id = "ZW", Name = "Zimbabwe" });

        context.SaveChanges();
    }
}

public class CountryRegionConfiguration : EntityTypeConfiguration<CountryRegion> // (*) Discovered by
{
    public CountryRegionConfiguration()
    {
        Property(e => e.Id)
            .IsRequired()
            .HasMaxLength(3);

        Property(e => e.Name)
            .IsRequired()
            .HasMaxLength(50);
    }
}

public partial class CountryRegion : IEntity<string>
{
    // Primary key 
    public string Id { get; set; }

    public string Name { get; set; }

}

public abstract class Entity<T> : IEntity<T>
{
    //Primary key
    public abstract T Id { get; set; }
}

public interface IEntity<T>
{
    T Id { get; set; }
}

我们可以看到,该种方法被一次又一次地运行。我们可以通过检查避免这种情况,如果迁移已经存在,因为当数据库创建一个自动应用..然后我们就可以重构DataDbConfiguration如下...

internal sealed class DataDbConfiguration : DbMigrationsConfiguration<DataDbContext>
{
    private readonly bool _isInitialized;

    public DataDbConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;

        var migrator = new DbMigrator(this);

        _isInitialized = migrator.GetDatabaseMigrations().Any();
    }

    protected override void Seed(DataDbContext context)
    {
        InitializeDatabase(context);
    }

    public void InitializeDatabase(DataDbContext context)
    {

        if (!_isInitialized)
        {
            if (context.Database.Connection.ConnectionString.Contains("localdb"))
            {
                DataSeedInitializer.Seed(context); // Seed Initial Test Data
            }
            else
            {
                // Do Seed Initial Production Data here
            }

        }
        else
        {
            // Do any recurrent Seed here
        }
    }
}


文章来源: Entity Framework Migrations - Enable AutoMigrations along with added migration