繁体   English   中英

实体框架,自动应用迁移

[英]Entity Framework, Automatic apply Migrations

我正在使用 Entity Framework Code First 方法和AutomaticMigrationsEnabled = true

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

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

项目的第一次运行按预期创建了数据库和表。 通过添加或删除字段更改我的 model 后,我运行了Add-Migration 生成了 Migration class 但在运行项目后出现此异常:

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

附加信息:支持“DBContext”上下文的 model 自数据库创建以来已更改。

编辑:根据arturo menchaca的回答中的指导,我像这样更改了我的代码:

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

...

更改后发生此异常:

数据库中已经有一个名为“MyTable”的 object。

如何应用我的数据库迁移?

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

如果在调用update-database时启用了自动迁移,如果模型中有待处理的更改,则会添加“自动”迁移并更新数据库。

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

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

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

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);
            }
        }
    }
}

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

之后在您的Global.asax

你需要有一些这样的代码

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

        migrator.Update();

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

Microsoft 在运行时解决迁移问题,请点击此处

例如,您可以在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.");
    }
}

使用 Microsoft.EntityFrameworkCore;

        await _dbContext.Database.MigrateAsync();
        _dbContext.Database.Migrate();

或者

        await _dbContext.Database.EnsureCreatedAsync();
         _dbContext.Database.EnsureCreated();

两种方法都检查数据库是否存在,如果不存在,它们都会创建它。

  • Migrate() 使用迁移,适用于使用迁移或关系数据库的情况。
  • EnsureCreated() 不使用迁移,这意味着一旦使用此方法创建了数据库,就无法对其执行进一步的迁移。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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