[英]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
.请注意,您应该宣布DbMigrationsConfiguration
和MigrateDatabaseToLatestVersion
与你的真实情境,而不是默认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.");
}
}
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.两种方法都检查数据库是否存在,如果不存在,它们都会创建它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.