Entity Framework,自动应用迁移
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;
}
}
项目的第一个 运行 按预期创建了数据库和表。通过添加或删除字段更改我的模型后,我 运行 Add-Migration
。迁移 class 已生成,但在 运行 项目后出现此异常:
An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
Additional information: The model backing the 'DBContext' context has
changed since the database was created.
编辑: 根据 arturo menchaca 答案中的指导,我这样更改了我的代码:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DBContext, MigrateDBConfiguration<DBContext>>());
...
更改后出现此异常:
There is already an object named 'MyTable' in the database.
如何应用我的数据库迁移?
Automatic Migrations 意味着您不需要 运行 add-migration
命令来更改模型,但您必须 运行 update-database
手动命令。
如果在您调用 update-database
时启用了 自动迁移 ,如果您的模型中有待处理的更改,将添加 'automatic' 迁移和数据库会更新的。
如果您希望更新数据库而不需要调用 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>
{
...
请注意,您应该使用真实上下文声明 DbMigrationsConfiguration
和 MigrateDatabaseToLatestVersion
,而不是默认的 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 在运行时处理迁移,here。
例如,您可以在 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() 不使用迁移,这意味着一旦使用此方法创建了数据库,就无法对其执行进一步的迁移。
我正在使用 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;
}
}
项目的第一个 运行 按预期创建了数据库和表。通过添加或删除字段更改我的模型后,我 运行 Add-Migration
。迁移 class 已生成,但在 运行 项目后出现此异常:
An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
Additional information: The model backing the 'DBContext' context has changed since the database was created.
编辑: 根据 arturo menchaca 答案中的指导,我这样更改了我的代码:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DBContext, MigrateDBConfiguration<DBContext>>());
...
更改后出现此异常:
There is already an object named 'MyTable' in the database.
如何应用我的数据库迁移?
Automatic Migrations 意味着您不需要 运行 add-migration
命令来更改模型,但您必须 运行 update-database
手动命令。
如果在您调用 update-database
时启用了 自动迁移 ,如果您的模型中有待处理的更改,将添加 'automatic' 迁移和数据库会更新的。
如果您希望更新数据库而不需要调用 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>
{
...
请注意,您应该使用真实上下文声明 DbMigrationsConfiguration
和 MigrateDatabaseToLatestVersion
,而不是默认的 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 在运行时处理迁移,here。
例如,您可以在 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() 不使用迁移,这意味着一旦使用此方法创建了数据库,就无法对其执行进一步的迁移。