实体框架代码优先迁移——不能删除约束,因为它不存在(从4.3到5.0的命名约定)

本文关键字:命名约定 不存在 因为 代码 框架 迁移 不能 实体 约束 删除 | 更新日期: 2023-09-27 18:19:21

以前使用的是EF 4.3,升级到5.0后,我发现索引、FK约束和PK约束的命名约定都更改为包含dbo(例如。PK_Users现在变成PK_dbo.Users)

现在,每当我对模型进行更改并且它需要更改包含这些的表时,它总是说它无法删除约束因为它找不到它

我只是希望当它试图删除约束/索引/键时,它首先检查5.0之前的命名是否存在,如果存在,则删除它,但仍然使用新的5.0命名约定重新创建它。

命名约定从4.3到5.0改变如下:

主键/索引
Old: PK_Users                    New: PK_dbo.Users

外键

Old: FK_Users_Roles_Role_Id      New: FK_dbo.Users_dbo.Roles_Role_Id               

注意:我不能简单地让EF重新生成所有的表,我在这个数据库中有生产数据。我也不想为使用自定义迁移的每个表手动执行此操作。

编辑:我发现了一个类似的问题,我如何阻止实体框架5迁移添加dbo。关键名称?但这个家伙只是想忽略5.0的约定,坚持4.3,它只处理表重命名。我不希望这样做,因为EF的后续版本可能会导致更多的变化,这将影响到这段代码,只是一个麻烦。

我试着做一些与答案相同的事情:

public class CodeMigrator : CSharpMigrationCodeGenerator
{
    protected override void Generate(
        DropIndexOperation dropIndexOperation, IndentedTextWriter writer)
    {
        dropIndexOperation.Name = StripDbo(dropIndexOperation.Name);
        base.Generate(dropIndexOperation, writer);
    }
    protected override void Generate(DropForeignKeyOperation dropForeignKeyOperation, IndentedTextWriter writer)
    {
        dropForeignKeyOperation.Name = StripDbo(dropForeignKeyOperation.Name);
        base.Generate(dropForeignKeyOperation, writer);
    }
    protected override void Generate(DropPrimaryKeyOperation dropPrimaryKeyOperation, IndentedTextWriter writer)
    {
        dropPrimaryKeyOperation.Name = StripDbo(dropPrimaryKeyOperation.Name);
        base.Generate(dropPrimaryKeyOperation, writer);
    }
    // TODO: Override other Generate overloads that involve table names
    private string StripDbo(string name)
    {
        return name.Replace("dbo.", "");
    }
}

并添加到配置:

public Configuration()
    {
        CodeGenerator = new CodeMigrator();
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = false;
    }

但是错误仍然出现:

dbo.Users_dbo。Departments_Department_Id'不是一个约束。不能放弃约束。见前面的错误。

我实际上尝试覆盖CSharpMigrationCodeGenerator中的每个成员并在返回语句上设置断点,但它们都没有命中。所以似乎我的自定义生成器从未被使用过,不确定我错过了什么。

实体框架代码优先迁移——不能删除约束,因为它不存在(从4.3到5.0的命名约定)

我找出了答案,它与我在问题中链接到的问题中的答案相似。覆盖CSharpCodeGenerator的问题仅用于自定义迁移

要覆盖自动迁移,您需要覆盖SqlServerMigrationSqlGenerator类并在迁移中调用SetSqlGenerator()。配置构造函数:

public class SqlMigrator : SqlServerMigrationSqlGenerator
{
    protected override void Generate(DropForeignKeyOperation dropForeignKeyOperation)
    {
        dropForeignKeyOperation.Name = StripDbo(dropForeignKeyOperation.Name);
        base.Generate(dropForeignKeyOperation);
    }
    protected override void Generate(DropIndexOperation dropIndexOperation)
    {
        dropIndexOperation.Name = StripDbo(dropIndexOperation.Name);
        base.Generate(dropIndexOperation);
    }
    protected override void Generate(DropPrimaryKeyOperation dropPrimaryKeyOperation)
    {
        dropPrimaryKeyOperation.Name = StripDbo(dropPrimaryKeyOperation.Name);
        base.Generate(dropPrimaryKeyOperation);
    }
    private string StripDbo(string name)
    {
        return name.Replace("dbo.", "");
    }
}

和迁移配置:

public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = false;
        SetSqlGenerator("System.Data.SqlClient", new SqlMigrator());
    }