Entity Framework 6 如何排序迁移
How does Entity Framework 6 order migrations
当数据库上下文配置为 MigrateDatabaseToLatestVersion
时,获得 运行 的迁移顺序是什么?自动生成的迁移 类 似乎不包含任何顺序。唯一似乎对顺序有线索的地方是迁移文件名/时间戳 - 但在 运行 时间似乎不太可能或不可用...对吗?
最初的迁移名称是实际使用的名称。这也与初始文件名相同,但您显然可以更改它。
在EntityFramework中,当您生成迁移时,您可能熟悉编辑文件以自定义迁移。
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Blogs",
c => new
{
BlogId = c.Int(nullable: false, identity: true),
Name = c.String(),
})
.PrimaryKey(t => t.BlogId);
}
public override void Down()
{
DropTable("dbo.Blogs");
}
}
但是也会生成一个设计器文件,它有一些您不应该编辑的属性:
[GeneratedCode("EntityFramework.Migrations", "6.4.4")]
public sealed partial class InitialCreate : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(InitialCreate));
string IMigrationMetadata.Id
{
get { return "202111200213248_InitialCreate"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
在 EF6 的 source code 中,您可以看到迁移反映在您的迁移程序集中:
从 DbMigration
继承的每个 class 都被使用,然后由 Id
属性.
排序
_migrations
= (from t in migrationsAssembly.GetAccessibleTypes()
where t.IsSubclassOf(typeof(DbMigration))
&& typeof(IMigrationMetadata).IsAssignableFrom(t)
&& t.GetPublicConstructor() != null
&& !t.IsAbstract()
&& !t.IsGenericType()
&& t.Namespace == migrationsNamespace
select (IMigrationMetadata)Activator.CreateInstance(t))
.Where(mm => !string.IsNullOrWhiteSpace(mm.Id) && mm.Id.IsValidMigrationId())
.OrderBy(mm => mm.Id)
.ToList();
即使您重命名文件,Id
在您创建迁移时仍将具有其初始值,保持迁移按 EF6 所见的词法 和 时间顺序排列它。
EFCore 几乎相同,只是它已从 属性 移动到设计器文件中的属性:
[DbContext(typeof(MyContext))]
[Migration("20211118001328_InititialCreate")]
partial class Init {}
并且 EFCore 在继承自 Migration
的 class 上查找该属性。
var items
= from t in Assembly.GetConstructibleTypes()
where t.IsSubclassOf(typeof(Migration))
&& t.GetCustomAttribute<DbContextAttribute>()?.ContextType == _contextType
let id = t.GetCustomAttribute<MigrationAttribute>()?.Id
orderby id
select (id, t);
当数据库上下文配置为 MigrateDatabaseToLatestVersion
时,获得 运行 的迁移顺序是什么?自动生成的迁移 类 似乎不包含任何顺序。唯一似乎对顺序有线索的地方是迁移文件名/时间戳 - 但在 运行 时间似乎不太可能或不可用...对吗?
最初的迁移名称是实际使用的名称。这也与初始文件名相同,但您显然可以更改它。
在EntityFramework中,当您生成迁移时,您可能熟悉编辑文件以自定义迁移。
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Blogs",
c => new
{
BlogId = c.Int(nullable: false, identity: true),
Name = c.String(),
})
.PrimaryKey(t => t.BlogId);
}
public override void Down()
{
DropTable("dbo.Blogs");
}
}
但是也会生成一个设计器文件,它有一些您不应该编辑的属性:
[GeneratedCode("EntityFramework.Migrations", "6.4.4")]
public sealed partial class InitialCreate : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(InitialCreate));
string IMigrationMetadata.Id
{
get { return "202111200213248_InitialCreate"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
在 EF6 的 source code 中,您可以看到迁移反映在您的迁移程序集中:
从 DbMigration
继承的每个 class 都被使用,然后由 Id
属性.
_migrations
= (from t in migrationsAssembly.GetAccessibleTypes()
where t.IsSubclassOf(typeof(DbMigration))
&& typeof(IMigrationMetadata).IsAssignableFrom(t)
&& t.GetPublicConstructor() != null
&& !t.IsAbstract()
&& !t.IsGenericType()
&& t.Namespace == migrationsNamespace
select (IMigrationMetadata)Activator.CreateInstance(t))
.Where(mm => !string.IsNullOrWhiteSpace(mm.Id) && mm.Id.IsValidMigrationId())
.OrderBy(mm => mm.Id)
.ToList();
即使您重命名文件,Id
在您创建迁移时仍将具有其初始值,保持迁移按 EF6 所见的词法 和 时间顺序排列它。
EFCore 几乎相同,只是它已从 属性 移动到设计器文件中的属性:
[DbContext(typeof(MyContext))]
[Migration("20211118001328_InititialCreate")]
partial class Init {}
并且 EFCore 在继承自 Migration
的 class 上查找该属性。
var items
= from t in Assembly.GetConstructibleTypes()
where t.IsSubclassOf(typeof(Migration))
&& t.GetCustomAttribute<DbContextAttribute>()?.ContextType == _contextType
let id = t.GetCustomAttribute<MigrationAttribute>()?.Id
orderby id
select (id, t);