简体   繁体   English

实体框架,自动应用迁移

[英]Entity Framework, Automatic apply Migrations

I am using Entity Framework Code First approach with AutomaticMigrationsEnabled = true :我正在使用 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;
    }
}

The first run of the project creates the database and tables as expected.项目的第一次运行按预期创建了数据库和表。 After changing my model by adding or dropping fields, I ran Add-Migration .通过添加或删除字段更改我的 model 后,我运行了Add-Migration The Migration class was generated but after running the project this exception occurs:生成了 Migration class 但在运行项目后出现此异常:

An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code EntityFramework.dll 中出现“System.InvalidOperationException”类型的异常,但未在用户代码中处理

Additional information: The model backing the 'DBContext' context has changed since the database was created.附加信息:支持“DBContext”上下文的 model 自数据库创建以来已更改。

EDIT: Per the guidance in the answer of arturo menchaca I changed my code like this:编辑:根据arturo menchaca的回答中的指导,我像这样更改了我的代码:

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

...

After the change this exception is occurring:更改后发生此异常:

There is already an object named 'MyTable' in the database.数据库中已经有一个名为“MyTable”的 object。

How can I apply my database migration?如何应用我的数据库迁移?

Automatic Migrations means that you don't need to run add-migration command for your changes in the models, but you have to run update-database command manually.自动迁移意味着您不需要为模型中的更改运行add-migration命令,但您必须手动运行update-database命令。

If Automatic Migrations is enabled when you call update-database , if there are pending changes in your models, an 'automatic' migration will be added and database will be updated.如果在调用update-database时启用了自动迁移,如果模型中有待处理的更改,则会添加“自动”迁移并更新数据库。

If you want that your database is updated without need to call update-database command, you can add Database.SetInitializer(...) in OnModelCreating() method on your context, like so:如果您希望更新数据库而无需调用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>
{
    ...

Note that you should declare DbMigrationsConfiguration and MigrateDatabaseToLatestVersion with your real context, not the default DbContext .请注意,您应该宣布DbMigrationsConfigurationMigrateDatabaseToLatestVersion与你的真实情境,而不是默认DbContext

Finally, I found a solution to my problem.最后,我找到了解决我的问题的方法。 I call this method in each application start :我在每个应用程序启动时调用此方法:

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

If you have change in your entities, you need first run add-migration to create the migration script.如果您的实体发生变化,您需要先运行add-migration来创建迁移脚本。

After that in your Global.asax之后在您的Global.asax

you need to have some code like this你需要有一些这样的代码

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

        migrator.Update();

every time that you run your asp.net project it'll check if you have a new migration to run and run update-database automatically for you.每次运行 asp.net 项目时,它都会检查您是否有新的迁移来运行并自动为您运行update-database

Microsoft addresses migrations at runtime, here . Microsoft 在运行时解决迁移问题,请点击此处

For example, you can do this in Program.cs : (tested working in .NET 5.0 preview)例如,您可以在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.");
    }
}

using Microsoft.EntityFrameworkCore;使用 Microsoft.EntityFrameworkCore;

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

OR或者

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

both method check if database exist, if not they both create it.两种方法都检查数据库是否存在,如果不存在,它们都会创建它。

  • Migrate() uses migrations and is suitable if you use migrations or relational database. Migrate() 使用迁移,适用于使用迁移或关系数据库的情况。
  • EnsureCreated() does not use migrations which means once db is created using this method no further migrations can be executed over it. EnsureCreated() 不使用迁移,这意味着一旦使用此方法创建了数据库,就无法对其执行进一步的迁移。

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

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