当我通过 EF Core 更新数据库时创建唯一索引重复键

CREATE UNIQUE INDEX duplicate key when I update-database by EF Core

我在迁移到数据库时遇到错误问题

The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'dbo.Cities' and the index name 'IX_Cities_CountryId'. The duplicate key value is (1). The statement has been terminated.

我为上下文 table 和列配置编写下一个代码:

public class CityConfiguration : IEntityTypeConfiguration<City>
    {
        public void Configure(EntityTypeBuilder<City> builder)
        {
            builder.HasKey(x => x.Id).HasName("PK_City_Id");
            builder.Property(x => x.Id).ValueGeneratedOnAdd();

            builder.HasIndex(x => x.Name).IsUnique().HasName("IX_dbo_Cities_Name");
            builder.Property(x => x.Name).HasMaxLength(64)
                                         .IsRequired();

            builder.Property(x => x.Region).HasMaxLength(64)
                                           .IsRequired();

            builder.Property(x => x.CountryId).IsRequired();

            builder.HasOne<Country>(x => x.Country)
                   .WithOne(x => x.City)
                   .HasForeignKey<City>(x => x.CountryId);

            builder.HasData(InitDefaultCities());
        }

        private City[] InitDefaultCities()
        {
            var cities = new City[]
            {
                new City() { Id = 1, Name = "Atlanta", Region = "Georgia", CountryId = 1,   },
                new City() { Id = 2, Name = "Boston", Region = "Massachusetts", CountryId = 1 },
                new City() { Id = 3, Name = "Brooklyn", Region = "New York", CountryId = 1 },
                new City() { Id = 4, Name = "Charlotte", Region = "North Carolina", CountryId = 1 },
                new City() { Id = 5, Name = "Chicago", Region = "Illinois", CountryId = 1 },
                new City() { Id = 6, Name = "Cleveland", Region = "Ohio", CountryId = 1 },
                new City() { Id = 7, Name = "Dallas", Region = "Texas", CountryId = 1 },
                new City() { Id = 8, Name = "Denver", Region = "Colorado", CountryId = 1 },
                new City() { Id = 9, Name = "Detroit", Region = "Michigan", CountryId = 1 },
                new City() { Id = 10, Name = "San Francisco", Region = "California", CountryId = 1 },
                new City() { Id = 11, Name = "Houston", Region = "Texas", CountryId = 1 },
                new City() { Id = 12, Name = "Indianapolis", Region = "Indiana", CountryId = 1 },
                new City() { Id = 13, Name = "Los Angeles", Region = "California", CountryId = 1 },
                new City() { Id = 14, Name = "Memphis", Region = "Tennessee", CountryId = 1 },
                new City() { Id = 15, Name = "Miami", Region = "Florida", CountryId = 1 },
                new City() { Id = 16, Name = "Milwaukee", Region = "Wisconsin", CountryId = 1 },
                new City() { Id = 17, Name = "Minneapolis", Region = "Minnesota", CountryId = 1 },
                new City() { Id = 18, Name = "New Orlean", Region = "‎Louisiana", CountryId = 1 },
                new City() { Id = 19, Name = "Manhattan", Region = "New York", CountryId = 1 },
                new City() { Id = 20, Name = "Oklahoma", Region = "Oklahoma City", CountryId = 1 },
                new City() { Id = 21, Name = "Orlando", Region = "Florida", CountryId = 1 },
                new City() { Id = 22, Name = "Philadelphia", Region = "Pennsylvania", CountryId = 1 },
                new City() { Id = 23, Name = "Phoenix", Region = "Arizona", CountryId = 1 },
                new City() { Id = 24, Name = "Portland", Region = "Oregon", CountryId = 1 },
                new City() { Id = 25, Name = "Sacramento", Region = "California", CountryId = 1 },
                new City() { Id = 26, Name = "San Antonio", Region = "Texas", CountryId = 1 },
                new City() { Id = 27, Name = "Toronto", Region = "Ontario", CountryId = 2 },
                new City() { Id = 28, Name = "Salt Lake City", Region = "Utah", CountryId = 1 },
                new City() { Id = 29, Name = "Washinton D.C.", Region = "Washinton", CountryId = 1 }

            };

            return cities;
        }
    }

添加迁移后它转换为

migrationBuilder.CreateTable(
            name: "Cities",
            schema: "dbo",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                Name = table.Column<string>(maxLength: 64, nullable: false),
                Region = table.Column<string>(maxLength: 64, nullable: false),
                CountryId = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_City_Id", x => x.Id);
                table.ForeignKey(
                    name: "FK_Cities_Countries_CountryId",
                    column: x => x.CountryId,
                    principalSchema: "dbo",
                    principalTable: "Countries",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

migrationBuilder.InsertData(
            schema: "dbo",
            table: "Cities",
            columns: new[] { "Id", "CountryId", "Name", "Region" },
            values: new object[,]
            {
                { 1, 1, "Atlanta", "Georgia" },
                { 28, 1, "Salt Lake City", "Utah" },
                { 26, 1, "San Antonio", "Texas" },
                { 25, 1, "Sacramento", "California" },
                { 24, 1, "Portland", "Oregon" },
                { 23, 1, "Phoenix", "Arizona" },
                { 22, 1, "Philadelphia", "Pennsylvania" },
                { 21, 1, "Orlando", "Florida" },
                { 20, 1, "Oklahoma", "Oklahoma City" },
                { 19, 1, "Manhattan", "New York" },
                { 18, 1, "New Orlean", "‎Louisiana" },
                { 17, 1, "Minneapolis", "Minnesota" },
                { 16, 1, "Milwaukee", "Wisconsin" },
                { 29, 1, "Washinton D.C.", "Washinton" },
                { 15, 1, "Miami", "Florida" },
                { 13, 1, "Los Angeles", "California" },
                { 12, 1, "Indianapolis", "Indiana" },
                { 11, 1, "Houston", "Texas" },
                { 10, 1, "San Francisco", "California" },
                { 9, 1, "Detroit", "Michigan" },
                { 8, 1, "Denver", "Colorado" },
                { 7, 1, "Dallas", "Texas" },
                { 6, 1, "Cleveland", "Ohio" },
                { 5, 1, "Chicago", "Illinois" },
                { 4, 1, "Charlotte", "North Carolina" },
                { 3, 1, "Brooklyn", "New York" },
                { 2, 1, "Boston", "Massachusetts" },
                { 14, 1, "Memphis", "Tennessee" },
                { 27, 2, "Toronto", "Ontario" }
            });

migrationBuilder.CreateIndex(
            name: "IX_Cities_CountryId",
            schema: "dbo",
            table: "Cities",
            column: "CountryId",
            unique: true);

        migrationBuilder.CreateIndex(
            name: "IX_dbo_Cities_Name",
            schema: "dbo",
            table: "Cities",
            column: "Name",
            unique: true);

找不到哪里麻烦,手写改成SQL脚本。不过数据不是问题,都是独一无二的。如果我评论唯一索引,它将正常工作。之后,我将通过文档

中的脚本检查数据
    SELECT 
    Name, 
    COUNT(Name)
FROM 
    dbo.Cities
GROUP BY 
    Name
HAVING 
    COUNT(Name) > 1;

结果显示为空!

您正在使用以下代码在列 CountryId 上创建唯一索引:

migrationBuilder.CreateIndex(
    name: "IX_Cities_CountryId",
    schema: "dbo",
    table: "Cities",
    column: "CountryId",
    unique: true);

由于这不是唯一的,我建议将 unique 设置为 false。可能是打字错误?

唯一索引是由 EF Core 生成的,因为您在 CityCountry 之间配置了一对一关系:

builder.HasOne<Country>(x => x.Country)
       .WithOne(x => x.City)
       .HasForeignKey<City>(x => x.CountryId);

显然这不是数据所要求的 - 这应该是一对多关系(City 有一个 Country,但 Country 有许多城市)。

因此,将 Country 中的 City 导航 属性 替换为这样的内容

public ICollection<City> Cities { get; set; }

分别

builder.HasOne(x => x.Country)
   .WithMany(x => x.Cities)
   .HasForeignKey(x => x.CountryId);

并且不要忘记重新生成迁移。