在一对多关系中从父集合中删除子实体时删除子实体 Entity Framework

Delete child entity when removed from parent collection in one to many relationship Entity Framework

我有以下数据库设置:

表格映射如下:

public class OrderMapping : EntityTypeConfiguration<Order>
{
    public OrderMapping()
    {
        this.ToTable("Orders", "prf");

        this.HasKey(o => o.OrderId);

        this.HasMany(o => o.OrderItems)
            .WithRequired(oi => oi.Order)
            .HasForeignKey(oi => oi.OrderId);

        this.HasRequired(o => o.Institution)
            .WithMany()
            .HasForeignKey(o => o.InstitutionId);

        this.Property(o => o.IsConfirmed)
            .IsRequired();

        this.Ignore(o => o.Id);
    }
}

public class OrderItemMapping : EntityTypeConfiguration<OrderItem>
{
    public OrderItemMapping()
    {
        this.ToTable("OrderItems", "prf");

        this.HasKey(oi => oi.OrderItemId);

        this.HasRequired(oi => oi.Order)
            .WithMany(oi => oi.OrderItems)
            .HasForeignKey(oi => oi.OrderId);

        this.HasRequired(oi => oi.Proficiency)
            .WithMany()
            .HasForeignKey(oi => oi.ProficiencyId);

        this.HasOptional(oi => oi.Enrolment)
            .WithMany()
            .HasForeignKey(oi => oi.EnrolmentId);

        this.HasMany(oi => oi.OrderItemSets)
            .WithRequired(ois => ois.OrderItem)
            .HasForeignKey(ois => ois.OrderItemId);

        this.Property(oi => oi.DateCreated);

        this.Ignore(oi => oi.Id);
    }
}

public class OrderItemSetMapping : EntityTypeConfiguration<OrderItemSet>
{
    public OrderItemSetMapping()
    {
        this.ToTable("OrderItemSets", "prf");

        this.HasKey(ois => ois.OrderItemSetId);

        this.HasRequired(ois => ois.OrderItem)
            .WithMany(ois => ois.OrderItemSets)
            .HasForeignKey(ois => ois.OrderItemId);

        this.Property(ois => ois.NumberOfSets);
        this.Property(ois => ois.Month);
    }
}

当我尝试从 OrderItem 的集合中删除 OrderItemSet 时 Entity Framework 试图将 OrderItemSet 中的外键设置为 null 而不是删除行,即使外键不可为 null,因此抛出异常说明外键不能设置为空。

this.OrderItemSets.Remove(orderItemSet);

我不知道我的映射有什么问题 Entity Framework 认为它应该将外键设置为 null 而不是删除行。

您需要的是 OderItemOrderItemSet 之间的 identifying relationship。来自上面提供的 link 中的 识别和非识别关系的注意事项 部分:

Removing the relationship deletes the dependent object. Calling the Remove method on the EntityCollection marks both the relationship and the dependent object for deletion.

您应该考虑 OrderOrderItem 的相同类型的关系。

基本思想是,对于 OrderItemSet 的模型,您将 OrderItem 的外键作为 OrderItemSet 的主键的一部分,从而创建 复合键。在 OrderItemSet 的映射中,尝试像这样映射主键:

public OrderItemSetMapping()
{
    ...

    this.HasKey(ois => new { ois.OrderItemSetId, ois.OrderItemId });

    ...
}

万一doesn't work with the fluent API,则尝试创建具有属性的映射:

public class OrderItemSet
{
    [Key, ForeignKey("OrderItem"), Column(Order = 1)]
    public <YourKeyType> OrderItemId { get; set; }

    [Key, Column(Order = 2)]
    public <YourKeyType> OrderItemSetId { get; set; }

    ...
}

为什么不直接删除 child:

context.OrderItemSets.Remove(orderItemSet);
context.SaveChanges();

当您从 parent 中删除 child 时,您可能想将其添加到另一个 parent,因此 Entity Framework 删除child 自动。你应该自己做。

我已经按照Abbondanza的建议解决了这个问题。首先创建包含外键的实体键(这将强制 entity framework 删除子项,因为没有外键它就不能存在):

public OrderItemSetMapping()
{
    ...

    this.HasKey(ois => new { ois.OrderItemSetId, ois.OrderItemId });

    ...
}

Entity Framework 现在将删除实体,如果从父集合中删除,但是由于 OrderItemSetId 是一个标识列,这会产生另一个问题,Entity Framework 现在想在该列中插入一个值将新项目添加到父集合时(这将抛出异常)。通过在此列上指定 DatabaseGenerationOption,问题将得到解决:

public OrderItemSetMapping()
{
    ...

    this.Property(r => r.OrderItemSetId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

    ...
}