【问题标题】:multiple added entities may have the same primary key for some cyclic entity对于某些循环实体,多个添加的实体可能具有相同的主键
【发布时间】:2020-08-02 15:34:25
【问题描述】:

我有一些循环实体,想通过附加导航对象来保存 EntityA 的所有细节 像 Entity B 和 EntityC 一样,但是当它尝试保存时得到“多个添加的实体可能有相同的主键错误”。所有表中的ID都是身份。基本上我想在表 C 中引用 A 和 B,在 B 中引用 A。`

 

     public class EntityA
    {
        [Key]
        public int QID { get; set; }
    
        public virtual List<EntityC> EntityCs { get; set; }
    
        public virtual List<EntityB> EntityBs { get; set; }
    }
    
    public class EntityB
    {
        [Key]
        public int OptionID { get; set; }
        public int QID { get; set; }
        [ForeignKey("QID")]
        public virtual EntityA EntityA { get; set; }
    }
       
    
     public class EntityC
     {
                [Key]
                public int CID { get; set; }
                public int QID { get; set; }
                public int OptionID { get; set; }
                [ForeignKey("QID")]
                public virtual EntityA EntityA { get; set; }
                [ForeignKey("OptionID")]
                public virtual EntityB Option { get; set; }
      }

【问题讨论】:

  • 我做了什么,我尝试在下面插入,因为 id 列是身份所以没有通过这个:Entity A a = new EntityA(); a.EntityBS = new List(); a.EntityCs = new List();然后 context.EntityAs.Add(a); context.saveChanges();但是出现错误,我认为 EF 没有像第一个 A--->B---->C 那样添加记录序列

标签: c# asp.net-mvc entity-framework ef-code-first


【解决方案1】:

确保您添加的是相同的跟踪实例引用。当开发人员假设具有相同 ID 的两个实例被解释为指向同一记录时,通常会导致此类错误,以便 EF 知道它们是同一事物。

例如:(错误)

var b = new B { Id = bId, A = new A { Id = aId }};
var c = new C { Id = cId, A = new A { Id = aId }};
context.Bs.Add(b);
context.Cs.Add(c);

b.A 和 c.A 指向“A”记录的 2 个单独实例。 (相同的 ID 但不同的实例)EF 将遇到这作为 2 个新的 A 记录并尝试插入两者。

假设本例中的“A”也是一条新记录:

var a = new A { Id = aId };
var b = new B { Id = bId, A = a };
var c = new C { Id = cId, A = a };
context.Bs.Add(b);
context.Cs.Add(c);

此示例的主要区别在于,我们实例化了“A”的一个新的单个实例,然后在我们的新 B 和 C 中引用它。当 Context 跟踪它时,它们将指向同一个实例。

但是,如果 A 实例应该已经存在于数据库中,甚至可能被 DbContext 跟踪:

var a = context.As.Single(a => a.Id == aId);
var b = new B { Id = bId, A = a };
var c = new C { Id = cId, A = a };
context.Bs.Add(b);
context.Cs.Add(c);

这确保了上下文应该知道的作为现有记录的 A 引用被加载并在新的 B 和 C 引用中使用。如果即使使用已经存在的 ID 创建新的 A,直接或通过新的 B 或 C 间接将其添加到 Context 将导致 EF 将其视为新记录并尝试插入它。如果将 ID 设置为身份列,这将导致重复的 PK 错误,或者更糟糕的是,出现静默问题,因为它可以插入具有您不期望的新 ID 的新“A”记录。

【讨论】:

    猜你喜欢
    • 2011-08-27
    • 2018-02-08
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 2016-06-14
    • 1970-01-01
    相关资源
    最近更新 更多