实体框架 4.1 Codefirst:“给定多重性约束”删除一对多子项时出错

发布于 2024-11-26 22:42:40 字数 2852 浏览 1 评论 0原文

我在Entity Framework 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”也必须在 “已删除”状态。

我尝试在这里遵循一些问题来解决问题,特别是尝试阅读 这个答案中提供的链接(这就是为什么从 MetaInformation 直接引用 MetaInformationObject 的原因),但我不知道出了什么问题。

I have the following classes in Entity Framework 4.1 (the classes have been pruned to keep the code readable)

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);
}

At one point, i'd like to update a machine information, so if it already exists in the database, i load it, attach it and then clear the previous metainformations to replace them with the new ones.

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();
}

And then, the following DbUpdateException is thrown:

A relationship from the 'MetaInformationObject_MetaInformations'
AssociationSet is in the 'Deleted' state. Given multiplicity
constraints, a corresponding
'MetaInformationObject_MetaInformations_Target' must also in the
'Deleted' state.

I tried following some questions here on SO to solve the problem, especially trying to read this one and the link provided in the answer (that's the reason why there's a direct reference from MetaInformation to MetaInformationObject) but i can't figure out what's wrong.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谎言月老 2024-12-03 22:42:40

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

  • 迭代所有相关的 MetaInformation 并删除它们中的每一个
  • 重构模型以定义 识别关系。之后,Clear 不仅会破坏关系,还会将相关实体标记为已删除。

Cascade delete will not help you here. Cascade delete works only if you delete parent entity (MetaInformationObject). The problem here is that calling Clear on the collection of related objects doesn't delete them. It only deletes the relation (= it will set foreign key in MetaInformation to null) but it is not allowed by your mapping constraints (you defined relation as required). The ways to avoid this are either:

  • Iterate through all related MetaInformations and delete each of them
  • Refactor you model to define identifying relation. After that Clear will not only break the relation but mark related entity as deleted as well.
一口甜 2024-12-03 22:42:40

呼应上面的评论,下面的代码可以解决您的问题

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

Echoing above comment, below code would solve your problem

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文