实体框架,自动应用迁移

时间:2016-03-28 15:50:16

标签: c# entity-framework ef-code-first ef-migrations

我首先使用Entity Framework代码,并通过以下代码设置AutomaticMigrationsEnabled:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<DbContext, MigrateDBConfiguration>());
//////////////////////////////////

public class MigrateDBConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<DbContext>
{
    public MigrateDBConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }
}

首次运行项目时,它可以正常工作并创建数据库和表。在我更改模型并删除一些字段或添加新字段并运行Add-Migration之后,生成了迁移类但在运行项目之后发生此异常:

  

EntityFramework.dll中出现'System.InvalidOperationException'类型的异常,但未在用户代码中处理

     

附加信息:支持'DBContext'上下文的模型具有   自数据库创建以来已更改。

编辑:arturo menchaca的答案一样,我可能会更改代码:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<DBContext, MigrateDBConfiguration<DBContext>>());

...

但例外情况是:

  

数据库中已有一个名为“MyTable”的对象。

我想申请迁移。

4 个答案:

答案 0 :(得分:15)

最后我找到了解决问题的方法。我在每个应用程序启动时调用此方法:

public void InitializeDatabase(DataAccessManager context)
{
    if (!context.Database.Exists() || !context.Database.CompatibleWithModel(false))
    {
        var configuration = new DbMigrationsConfiguration();
        var migrator = new DbMigrator(configuration);
        migrator.Configuration.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString, "System.Data.SqlClient");
        var migrations = migrator.GetPendingMigrations();
        if (migrations.Any())
        {
            var scriptor = new MigratorScriptingDecorator(migrator);
            var script = scriptor.ScriptUpdate(null, migrations.Last());

            if (!string.IsNullOrEmpty(script))
            {
                context.Database.ExecuteSqlCommand(script);
            }
        }
    }
}

答案 1 :(得分:14)

自动迁移意味着您不需要为模型中的更改运行add-migration命令,但您必须手动运行update-database命令。 / p>

如果在致电update-database时启用了自动迁移,则如果您的模型中有待处理的更改,则会自动启用&#39;将添加迁移并更新数据库。

如果您希望更新数据库而无需调用update-database命令,则可以在Database.SetInitializer(...)方法中添加OnModelCreating(),例如:

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, MigrateDBConfiguration>());
    }

    ...
}

public class MigrateDBConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<MyContext>
{
    ...

请注意,您应该使用真实背景声明DbMigrationsConfigurationMigrateDatabaseToLatestVersion,而不是默认DbContext

答案 2 :(得分:3)

如果您的实体发生了变化,则需要先运行add-migration来创建迁移脚本。

之后在Global.asax

你需要有一些像这样的代码

        var configuration = new MyProject.Configuration();
        var migrator = new System.Data.Entity.Migrations.DbMigrator(configuration);            

        migrator.Update();

每次运行asp.net项目时,都会检查是否有新的迁移运行并自动运行update-database

答案 3 :(得分:0)

Microsoft在运行时解决迁移问题,这里:https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=vs#apply-migrations-at-runtime

例如,您可以在Program.cs中执行此操作:(已在.NET 5.0预览版中经过测试)

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    MigrateDatabase(host);

    host.Run();
}

private static void MigrateDatabase(IHost host)
{
    using var scope = host.Services.CreateScope();
    var services = scope.ServiceProvider;

    try
    {
        var context = services.GetRequiredService<ApplicationDbContext>();
        context.Database.Migrate();
    }
    catch (Exception ex)
    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "An error occurred creating the DB.");
    }
}