直接使用EF分配外键时无法插入重复键

时间:2017-11-14 00:58:52

标签: entity-framework

型号:

class TableA
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID {get;set;}
}

class TableB
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID {get;set;}
    public int TableAID {get;set;}
    [ForeignKey("TableAID")]
    public virtual TableA TableA {get;set;}
}

代码:

var copyB = sourceDb.TableB.Single(B => B.ID == TableBID_Param); //EG. B.ID == 17
copyB.TableAID = TableAID_Param; //EG. B.TableAID = 5;
destDb.TableB.Add(copyB);
destDb.SaveChanges(); //Error occurs here

我更改了外键ID,并且应该重新生成主键

1 个答案:

答案 0 :(得分:0)

这里的问题是copyB对象是:

  • 仍然与sourceDb
  • 相关联
  • 可能延迟加载TableA(如果TableAID有值)

TableA导航属性优先于TableAID外键属性。 DestDb将尝试插入TableA对象,这可能已经存在(可能来自之前成功执行此有缺陷的代码)。

您应该在上下文之间隔离对象,就像在向Web客户端发送数据时应该使用单独的ViewModel一样 - 您可以控制它如何被序列化。这也使未来的开发人员明白需要一个新的主键(未暗示)

扩展表B:

class TableB
{
    public string SomeData {get;set;} //Let's pretend there's something interesting to clone

    public TableA ContextClone()
    {
        var clone = new TableA();
        clone.SomeData = SomeData;
        //Nothing else get's assigned - it's up to the caller to map ForeignKeys
    }
}

新守则:

var sourceB= sourceDb.TableB.Single(B => B.ID == TableBID_Param); //EG. B.ID == 17
var clone = sourceB.ContextClone();
clone.TableAID = TableAID_Param; //EG. B.TableAID = 5;
destDb.TableB.Add(clone);
destDb.SaveChanges();