简体   繁体   English

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

[英]Entity Framework Code-First Migrations - Cannot drop constraint because it doesn't exist (naming convention from 4.3 to 5.0)

Was previously using EF 4.3 and upon upgrading to 5.0 I find out the Indexes, FK constraints, and PK constraints all have had their naming conventions changed to include dbo (eg. PK_Users has now become PK_dbo.Users) 以前使用EF 4.3并在升级到5.0时我发现索引,FK约束和PK约束都将其命名约定更改为包含dbo(例如PK_Users现在变为PK_dbo.Users)

Now anytime I make a change to the model and it needs to change a table that has these in it, it always says it can't drop constraint because it can't find it. 现在,每当我对模型进行更改并且需要更改包含这些内容的表时,它总是说它不能删除约束,因为它无法找到它。

I just want it so that when it tries to drop a constraint/index/key it first checks to see if the pre-5.0 naming one exists and if so drop it, but still re-create it using the new 5.0 naming conventions. 我只是想要它,以便当它试图删除约束/索引/键时,它首先检查5.0之前的命名是否存在,如果是,则删除它,但仍然使用新的5.0命名约定重新创建它。

The naming conventions changed like so from 4.3 to 5.0: 命名约定从4.3更改为5.0:

Primary Key/Indexes 主键/索引

Old: PK_Users                    New: PK_dbo.Users

Foreign Keys 外键

Old: FK_Users_Roles_Role_Id      New: FK_dbo.Users_dbo.Roles_Role_Id               

Note: I CANNOT simply have EF regenerate all the tables, I have production data in this database. 注意:我不能简单地让EF重新生成所有表,我在这个数据库中有生产数据。 I also don't want to have to manually do this for every table using custom migrations. 我也不想为每个使用自定义迁移的表手动执行此操作。

Edit: I found a similar question How can I stop Entity Framework 5 migrations adding dbo. 编辑:我发现了一个类似的问题如何停止添加dbo的Entity Framework 5迁移。 into key names? 成为关键名称? but this guy just wanted ignore 5.0 conventions and stick with 4.3, and it only dealt with table renaming. 但是这个家伙只是想忽略5.0惯例并坚持使用4.3,它只处理表重命名。 I'd prefer not to do that as subsequent versions of EF may cause more changes that would affect this code and just be a hassle down the line. 我不希望这样做,因为后续版本的EF可能会导致更多的更改,这些更改会影响此代码并且只是麻烦。

I tried doing something in the same vein as the answer posted: 我试着按照发布​​的答案做同样的事情:

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.", "");
    }
}

And adding it to the config: 并将其添加到配置:

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

    }

However the error still hits: 但是错误仍然存​​在:

dbo.Users_dbo.Departments_Department_Id' is not a constraint. dbo.Users_dbo.Departments_Department_Id'不是约束。 Could not drop constraint. 无法删除约束。 See previous errors. 查看以前的错误。

I actually tried override every single member in the CSharpMigrationCodeGenerator and setting a breakpoint on the return statement, and none of them hit. 我实际上尝试覆盖CSharpMigrationCodeGenerator中的每个成员并在return语句上设置断点,但没有一个成功。 So it appears my custom generator never gets used, not sure what I am missing with that. 所以看来我的自定义生成器永远不会被使用,不知道我错过了什么。

I figured out the answer and it's similar to the answer in the question I linked to in my question. 我找到了答案,它与我在问题中链接的问题中的答案类似。 The problem overriding CSharpCodeGenerator is only used in custom migrations . 覆盖CSharpCodeGenerator的问题仅用于自定义迁移

To override the automatic migrations you need to override the SqlServerMigrationSqlGenerator class and call SetSqlGenerator() in the Migration.Configuration constructor: 要覆盖自动迁移,您需要覆盖SqlServerMigrationSqlGenerator类并在Migration.Configuration构造函数中调用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.", "");
    }
}

And the migration config: 和迁移配置:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM