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