首页 > 解决方案 > 如何首先在 c# EF core 2.0 代码中强制迁移顺序

问题描述

我有两个表:“父母”和“孩子”:

public class Parent
{
    public int Id { get; set; }
    public string ExternalId { get; set; }
    public string Description { get; set; }
}
public class Child
{
    public int Id { get; set; }
    public string ExternalId { get; set; }
    public string Description { get; set; }
    public string ParentExternalId { get; set; }
}

这将生成以下 SQL 脚本:

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20171222072010_Initial')
BEGIN
    CREATE TABLE [Parents] (
        [Id] int NOT NULL IDENTITY,
        [ExternalId] nvarchar(50) NOT NULL,
        [Description] nvarchar(300) NULL,
        CONSTRAINT [PK_Parents] PRIMARY KEY ([Id])
    );
END;

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20171222072010_Initial')
BEGIN
    CREATE TABLE [Children] (
        [Id] int NOT NULL IDENTITY,
        [ExternalId] nvarchar(50) NOT NULL,
        [Description] nvarchar(300) NULL,
        [ParentExternalId] nvarchar(50) NOT NULL,
        CONSTRAINT [PK_Children] PRIMARY KEY ([Id])
    );
END;

现在我更改 Child 中的外键:

public class Child
{
    public int Id { get; set; }
    public string ExternalId { get; set; }
    public string Description { get; set; }
    #region foreign keys
    public int ParentId { get; set; }
    public Parent Parent { get; set; }
    #endregion foreign keys
}

这会生成这个 SQL 脚本:

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20180604085531_ChangeForeignKey')
BEGIN
    DECLARE @var49 sysname;
    SELECT @var49 = [d].[name]
    FROM [sys].[default_constraints] [d]
    INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
    WHERE ([d].[parent_object_id] = OBJECT_ID(N'Children') AND [c].[name] = N'ParentExternalId');
    IF @var49 IS NOT NULL EXEC(N'ALTER TABLE [Transactions] DROP CONSTRAINT [' + @var49 + '];');
    ALTER TABLE [Children] DROP COLUMN [ParentExternalId];
END;

GO

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20180604085531_ChangeForeignKey')
BEGIN
    ALTER TABLE [Children] ADD [ParentId] int NOT NULL DEFAULT 0;
END;

GO

IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20180604085531_ChangeForeignKey')
BEGIN
    ALTER TABLE [Children] ADD CONSTRAINT [FK_Children_Parents_ParentId] FOREIGN KEY ([ParentId]) REFERENCES [Parents] ([Id]) ON DELETE NO ACTION;
END;
GO

由于迁移中的顺序,我丢失了数据。我希望脚本首先添加新列“ParentId”,然后更新新列,然后删除列“ParentExternalId”。

有没有办法我可以强制这样做?

标签: c#entity-frameworkentity-framework-core

解决方案


我找到了。只需编辑 migration.cs 文件。它包含类似 migrationBuilder.AddColumn... 将其移至 migrationBuilder.DropColumn...

在两者之间您可以手动添加:

migrationBuilder.Sql(
@"
    UPDATE c SET c.ParentId = p.Id
    FROM Children AS c
    INNER JOIN Parents AS p ON ...
    WHERE c.ParentId <> p.Id
");

推荐阅读