实体框架:在所有迁移之前运行代码
本文关键字:运行 代码 迁移 框架 实体 | 更新日期: 2023-09-27 18:19:14
我想迁移数据库中的存储过程和视图。因为我总是迁移到最新版本,所以一个对源代码控制友好的方法是在迁移过程中删除/重新创建所有过程/视图(使用这种方法,每个过程有一个文件,而不是每个版本一个文件)。
由于旧的过程/函数/视图可能与新的模式更改不兼容,我想在所有迁移之前做drop,然后再做create。
以前我使用自定义的FluentMigrator,但现在我正在研究实体框架代码优先迁移。我看到我可以使用Seed
在所有迁移之后始终运行代码。
在所有迁移之前,我是否可以使用某些东西来始终运行代码 ?
如果希望在迁移开始之前运行一些代码,可以指定一个自定义数据库初始化器:
public class AwesomeEntity
{
public int Id { get; set; }
}
public class AwesomeDbContext : DbContext
{
static AwesomeDbContext()
{
Database.SetInitializer(new AwesomeDatabaseInitializer());
}
public IDbSet<AwesomeEntity> Entities { get; set; }
}
public class AwesomeDatabaseInitializer : MigrateDatabaseToLatestVersion<AwesomeDbContext, AwesomeMigrationsConfiguration>
{
public override void InitializeDatabase(AwesomeDbContext context)
{
// TODO: Run code before migration here...
base.InitializeDatabase(context);
}
}
public class AwesomeMigrationsConfiguration : DbMigrationsConfiguration<AwesomeDbContext>
{
public AwesomeMigrationsConfiguration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(AwesomeDbContext context)
{
// TODO: Seed database here...
}
}
这将自定义初始化器设置为自定义AwesomeDatabaseInitializer
,它继承自MigrateDatabaseToLatestVersion
。如果每次都想删除并重新构建数据库,则应该使用DropCreateDatabaseAlways
作为基类,尽管我不确定这是否允许运行迁移。
在初始化器中,您可以覆盖InitializeDatabase
方法,您可以在调用base.InitializeDatabase
之前运行代码,这将触发数据库初始化,进而触发迁移配置AwesomeMigrationsConfiguration
的Seed
方法。
这是使用EF6。我不确定在早期版本的实体框架中是否有等效的
我有一个非常可怕的解决方案,但适用于migrate.exe。
思路如下:
- 按照@khellang的建议,使用Seed for AfterAll。
- 对于BeforeAll,在MigrationsConfiguration构造器中注册一个自定义
IDbConnectionInterceptor
,以便在MigrationsConfiguration创建后捕获第一个连接,然后使其取消注册。显然,绝对是不是线程安全的,只有在应用程序启动或migrate.exe时才可以。
示例代码:
public class DbMigrationsInterceptingConfiguration<TContext> : DbMigrationsConfiguration<TContext>
where TContext : DbContext
{
public DbMigrationsInterceptingConfiguration() {
BeforeFirstConnectionInterceptor.InterceptNext();
}
protected override void Seed(TContext context) {
Console.WriteLine("After All!");
}
}
internal class BeforeFirstConnectionInterceptor : IDbConnectionInterceptor {
public static void InterceptNext() {
DbInterception.Add(new BeforeFirstConnectionInterceptor());
}
public void Opened(DbConnection connection, DbConnectionInterceptionContext interceptionContext) {
// NOT thread safe
Console.WriteLine("Before All!");
DbInterception.Remove(this);
}
// ... empty implementation of other methods in IDbConnectionInterceptor
}
我不确定我是否真的会使用它。