为什么我的 Required 属性 没有在 Entity Framework Core 中级联删除?
Why does my Required property not being cascade deleted in Entity Framework Core?
我有以下 class 和必需的 属性,并且 运行 遇到通过级联删除删除依赖属性的问题。
public class City
{
[Key]
public int Id {get; private set; }
[Required]
public ZipCode ZipCode { get; private set; }
}
public class ZipCode
{
[Key]
public int Id { get; private set; }
[Required]
public string Zip { get; private set; }
}
如果我尝试加载城市并使用以下代码将其删除:
City toDelete = db.CitySet.Where(c => c.Id == myCityReference.Id).FirstOrDefault();
db.CitySet.Remove(toDelete);
db.SaveChanges();
我得到一个 Microsoft.EntityFrameworkCore.DbUpdateException
,其内部异常是 Npgsql.PostgresException: 23503: Update or delete on table "..." violates foreign key constraint.
。
但是,如果我在上面加上一个include语句,那就是:
City toDelete = db.CitySet.Include(c => c.ZipCode)
.Where(c => c.Id == myCityReference.Id).FirstOrDefault();
然后删除成功删除了城市和邮政编码。但是,根据 EFCore docs,Required 关系将设置为 Cascade
删除功能。为什么这没有发生?我正在使用 Entity Framework Core v1.1.1 和 Npgsql v3.2.2。
这是从您的模型生成的迁移:
migrationBuilder.CreateTable(
name: "ZipCodes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Zip = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ZipCodes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Cities",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
ZipCodeId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Cities", x => x.Id);
table.ForeignKey(
name: "FK_Cities_ZipCodes_ZipCodeId",
column: x => x.ZipCodeId,
principalTable: "ZipCodes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Cities_ZipCodeId",
table: "Cities",
column: "ZipCodeId");
(针对Sql服务器,除了一些特定的标识列注解外,其他数据库类型应该是一样的)
如您所见,FK 是在启用级联删除的情况下创建的。但是,FK 列在 City
table 中并且引用 ZipCode
table。这意味着 ZipCode
是委托人,City
是受抚养人。所以删除 ZipCode
会级联删除 City
,反之亦然。
ZipCodeId
列上也没有唯一的 constraint/index,这表明 EF Core 假定 one-to-many
关系(一个 ZipCode
到多个 City
) .
如果你想让它反方向级联,那么你需要把FK列放在ZipCode
table中,使用下面的fluent配置:
modelBuilder.Entity<City>()
.HasOne(e => e.ZipCode)
.WithOne()
.HasForeignKey<ZipCode>("CityId")
.OnDelete(DeleteBehavior.Cascade);
现在迁移看起来像这样:
migrationBuilder.CreateTable(
name: "Cities",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
},
constraints: table =>
{
table.PrimaryKey("PK_Cities", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ZipCodes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
CityId = table.Column<int>(nullable: true),
Zip = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ZipCodes", x => x.Id);
table.ForeignKey(
name: "FK_ZipCodes_Cities_CityId",
column: x => x.CityId,
principalTable: "Cities",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ZipCodes_CityId",
table: "ZipCodes",
column: "CityId",
unique: true);
即级联是从 City
到 ZipCode
,关系是 one-to-one
(注意唯一索引)。
现在,我不确定这里的真正意图是什么。但可以肯定的是,数据库级联删除是定向的——从引用 table 到引用 table.
我有以下 class 和必需的 属性,并且 运行 遇到通过级联删除删除依赖属性的问题。
public class City
{
[Key]
public int Id {get; private set; }
[Required]
public ZipCode ZipCode { get; private set; }
}
public class ZipCode
{
[Key]
public int Id { get; private set; }
[Required]
public string Zip { get; private set; }
}
如果我尝试加载城市并使用以下代码将其删除:
City toDelete = db.CitySet.Where(c => c.Id == myCityReference.Id).FirstOrDefault();
db.CitySet.Remove(toDelete);
db.SaveChanges();
我得到一个 Microsoft.EntityFrameworkCore.DbUpdateException
,其内部异常是 Npgsql.PostgresException: 23503: Update or delete on table "..." violates foreign key constraint.
。
但是,如果我在上面加上一个include语句,那就是:
City toDelete = db.CitySet.Include(c => c.ZipCode)
.Where(c => c.Id == myCityReference.Id).FirstOrDefault();
然后删除成功删除了城市和邮政编码。但是,根据 EFCore docs,Required 关系将设置为 Cascade
删除功能。为什么这没有发生?我正在使用 Entity Framework Core v1.1.1 和 Npgsql v3.2.2。
这是从您的模型生成的迁移:
migrationBuilder.CreateTable(
name: "ZipCodes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Zip = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ZipCodes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Cities",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
ZipCodeId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Cities", x => x.Id);
table.ForeignKey(
name: "FK_Cities_ZipCodes_ZipCodeId",
column: x => x.ZipCodeId,
principalTable: "ZipCodes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Cities_ZipCodeId",
table: "Cities",
column: "ZipCodeId");
(针对Sql服务器,除了一些特定的标识列注解外,其他数据库类型应该是一样的)
如您所见,FK 是在启用级联删除的情况下创建的。但是,FK 列在 City
table 中并且引用 ZipCode
table。这意味着 ZipCode
是委托人,City
是受抚养人。所以删除 ZipCode
会级联删除 City
,反之亦然。
ZipCodeId
列上也没有唯一的 constraint/index,这表明 EF Core 假定 one-to-many
关系(一个 ZipCode
到多个 City
) .
如果你想让它反方向级联,那么你需要把FK列放在ZipCode
table中,使用下面的fluent配置:
modelBuilder.Entity<City>()
.HasOne(e => e.ZipCode)
.WithOne()
.HasForeignKey<ZipCode>("CityId")
.OnDelete(DeleteBehavior.Cascade);
现在迁移看起来像这样:
migrationBuilder.CreateTable(
name: "Cities",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
},
constraints: table =>
{
table.PrimaryKey("PK_Cities", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ZipCodes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
CityId = table.Column<int>(nullable: true),
Zip = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ZipCodes", x => x.Id);
table.ForeignKey(
name: "FK_ZipCodes_Cities_CityId",
column: x => x.CityId,
principalTable: "Cities",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ZipCodes_CityId",
table: "ZipCodes",
column: "CityId",
unique: true);
即级联是从 City
到 ZipCode
,关系是 one-to-one
(注意唯一索引)。
现在,我不确定这里的真正意图是什么。但可以肯定的是,数据库级联删除是定向的——从引用 table 到引用 table.