CREATE UNIQUE INDEX 语句终止,因为发现重复键 EF

问题描述

我正在使用实体框架和 C# 构建一个应用程序,在我的一个表中,我注意到我将主键命名为与外键列相同的名称,即 dbo.MembershipTypes 表的主键是在“MembershipTypeId”属性上,并且与它有关系的 dbo.Customers 表在“MembershipTypeId”属性上有一个外键,即 public MembershipType MembershipTypeId { get; set; })

这引起了问题,因此我将 MembershipTypeId 重命名Id(它最初是 Id,但该列不是标识列,EF 拒绝将其设为一个偶数使用 [DatabaseGenereated(DatabaseGeneratedOption.Identity)][Key] 属性后)。

我使用的是代码优先迁移,所以当我尝试使用

恢复更改时
update-database -TargetMigration:(migration before mistake goes here)

在包管理器控制台中,我收到此错误

CREATE UNIQUE INDEX 语句终止,因为找到了对象名称“dbo.MembershipTypes”和索引名称“PK_dbo.MembershipTypes”的重复键。重复的键值为 (0)。 无法创建约束或索引。查看以前的错误

这是当我尝试恢复到数据库的早期版本时它给我错误的迁移:

public partial class RenameIdColumnAndMakeItIdentityInMembershipTypeTable : DbMigration
{
    public override void Up()
    {
        DropForeignKey("dbo.Customers","MembershipTypeId","dbo.MembershipTypes");
        DropPrimaryKey("dbo.MembershipTypes");
        AddColumn("dbo.MembershipTypes",c => c.Byte(nullable: false,identity: true));
        AddPrimaryKey("dbo.MembershipTypes","MembershipTypeId");
        AddForeignKey("dbo.Customers","dbo.MembershipTypes",cascadeDelete: true);
        DropColumn("dbo.MembershipTypes","Id");
    }
    
    public override void Down()
    {
        AddColumn("dbo.MembershipTypes","Id",c => c.Byte(nullable: false));
        DropForeignKey("dbo.Customers","dbo.MembershipTypes");
        DropPrimaryKey("dbo.MembershipTypes");
        DropColumn("dbo.MembershipTypes","MembershipTypeId");
        AddPrimaryKey("dbo.MembershipTypes","Id");
        AddForeignKey("dbo.Customers",cascadeDelete: true);
    }
}

这是用于创建表的 T-sql 代码 EF。我首先用它的属性制作了表格,然后在单独的迁移中用参考数据填充它。

CREATE TABLE [dbo].[MembershipTypes] 
(
    [SignUpFee]        SMALLINT      NOT NULL,[DurationInMonths] tinyint       NOT NULL,[discountRate]     tinyint       NOT NULL,[Name]             NVARCHAR(255) DEFAULT ('') NOT NULL,[MembershipTypeId] tinyint IDENTITY (1,1) NOT NULL,CONSTRAINT [PK_dbo.MembershipTypes] 
        PRIMARY KEY CLUSTERED ([MembershipTypeId] ASC)
);

以下是用于生成客户表的代码

CREATE TABLE [dbo].[Customers] 
(
    [Id]                       INT            IDENTITY (1,[Name]                     NVARCHAR (255) NOT NULL,[IsSubscribedToNewsletter] BIT            DEFAULT ((0)) NOT NULL,[MembershipTypeId]         tinyint        DEFAULT ((0)) NOT NULL,[Birthdate]                DATETIME       NULL,CONSTRAINT [PK_dbo.Customers] 
        PRIMARY KEY CLUSTERED ([Id] ASC),CONSTRAINT [FK_dbo.Customers_dbo.MembershipTypes_MembershipTypeId] 
        FOREIGN KEY ([MembershipTypeId]) REFERENCES [dbo].[MembershipTypes] ([MembershipTypeId]) 
            ON DELETE CASCADE
);
GO

CREATE NONCLUSTERED INDEX [IX_MembershipTypeId]
ON [dbo].[Customers]([MembershipTypeId] ASC);

这一切都是在我尝试修复 API 以使用 [HttpPost] 创建新客户时发生的。

请帮助我理解为什么我会收到此错误以及如何修复它。另外,请帮助我理解为什么重复键从 0 而不是 1 开始。

预先感谢您的帮助!

解决方法

感谢 Gert Arnold 在评论中回答这个问题。

我收到此错误的原因是我迁移的 Id 方法中的 Down 列不是标识列。

我的理解是,由于在关系数据库中通常具有主键的 Id 列不能为空,因此在那里插入 0,因为这是字节或整数类型的默认值。>

在我的 Up 方法中,我将 Id 设为标识列,但是由于默认值 0 已经存在,这造成了冲突,因为数据库现在正在为 {{1} 生成一个值}} 从 0 开始。

这行不通,因为 Id 列是唯一的,不能有重复的值。例如,即使您的数据库中有 5 个客户并删除了客户 4,也没有其他客户的 ID 为 4。

希望这对未来的人有所帮助!