4.1代码优先:“给定多重约束”删除一对多子节点时出错

本文关键字:约束 删除 一对多 出错 子节点 代码 | 更新日期: 2023-09-27 18:03:49

我在实体框架4.1中有以下类(这些类已被修剪以保持代码可读)

public class MetaInformation
{
    public int Id { get; set; }
    public virtual MetaInformationObject RelatedTo { get; set; }
}
public abstract class MetaInformationObject
{
    public int Id { get; set; }
    public virtual List<MetaInformation> MetaInformations { get; set; }
}
[Table("Hardwares")]
public class Hardware : MetaInformationObject
{
    [MaxLength(100)]
    public string Name { get; set; }
}
public class Inventory
{
    public int Id { get; set; }
    public virtual List<Machine> Machines { get; set; }
}
public class Machine : Hardware
{
    public Inventory Inventory { get; set; }
}
 protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Isis.Business.Base.MetaInformationObject>()
        .HasMany<Isis.Business.Base.MetaInformation>(mi => mi.MetaInformations).WithRequired(mi => mi.RelatedTo).WillCascadeOnDelete(true);
    modelBuilder.Entity<Isis.Business.Inventory.Inventory>()
            .HasMany<Isis.Business.Inventory.Machine>(i => i.Machines).WithRequired(m => m.Inventory).WillCascadeOnDelete(true);
    base.OnModelCreating(modelBuilder);
}

在某一点上,我想更新一个机器信息,所以如果它已经存在于数据库中,我加载它,附加它,然后清除以前的元信息,用新的元信息代替它们。

public void UpdateMachine(Inventory i, Machine m)
{
    DataContext.Dao.Db.Inventories.Attach(i);
    if (!i.Machines.Exists(InnerHardware => InnerHardware.SerialNumber == m.SerialNumber)) {
        i.Machines.Add(m);
    } else {
        var workingMachine = i.Machines.First(Machine => Machine.SerialNumber == m.SerialNumber);
        Dao.Db.Machines.Attach(workingMachine);
        if (workingMachine.MetaInformations != null && workingMachine.MetaInformations.Count > 0) {
            workingMachine.MetaInformations.Clear();
            //workingMachine.MetaInformations.ForEach(mi => { Dao.Db.MetaInformations.Attach(mi); Dao.Db.MetaInformations.Remove(mi); }); // tried this to, with variations
        }
        workingMachine.MetaInformations = m.MetaInformations;
    }
    DataContext.Dao.Db.SaveChanges();
}

然后,抛出以下DbUpdateException:

来自'MetaInformationObject_MetaInformations'的关系日志含义AssociationSet处于删除状态。给定的多重性约束条件,相应的'MetaInformationObject_MetaInformations_Target'也必须在"删除"状态。

我试着在SO上遵循一些问题来解决问题,特别是试图阅读这个问题和答案中提供的链接(这就是为什么从MetaInformationMetaInformationObject有直接参考的原因),但我不知道出了什么问题。

4.1代码优先:“给定多重约束”删除一对多子节点时出错

级联删除在这里没有帮助。只有删除父实体(MetaInformationObject)时才会进行级联删除。这里的问题是,对相关对象集合调用Clear并不会删除它们。它只删除关系(=它将MetaInformation中的外键设置为null),但映射约束不允许这样做(您根据需要定义关系)。避免这种情况的方法有:

  • 遍历所有相关的MetaInformation并逐一删除
  • 重构你的模型来定义识别关系。之后,Clear不仅会打破关系,而且会将相关实体标记为已删除。

与上面的注释相同,下面的代码将解决您的问题

DataContext.Dao.Db.MetaInformations.RemoveRange (workingMachine.MetaInformations);