2015-10-17 79 views
2

我有一个代码,第一EF模型是这样的:实体框架外键插入重复键

public partial class A 
{ 
    [Key] 
    [StringLength(7)] 
    public string Code { get; set; } 

    [Required] 
    [StringLength(100)] 
    public string Name { get; set; } 


    public virtual ICollection<B> Bs { get; set; } 
} 

public partial class B 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    [Required] 
    [StringLength(100)] 
    public string Name { get; set; } 

    [Required] 
    [StringLength(7)] 
    [ForeignKey("A")] 
    public string ACode { get; set; } 

    public virtual A A { get; set; } 
} 

当我将这样的数据:

var a = new A(); 
a.Code = "A0"; 
a.Name = "A Name"; 

var b = new B(); 
b.Name = "B Name"; 
b.ACode = a.Code; 
b.A = a; 

using (DbContext context = new DbContext()) 
{ 
     context.As.Add(a); 
     context.Bs.Add(b); 
     context.SaveChanges(); 
} 

var b2 = new B(); 
b2.Name = "B Name 2"; 
b2.ACode = a.Code; 
b2.A = a; 

using (DbContext context = new DbContext()) 
{ 
     context.Bs.Add(b2); 
     context.SaveChanges(); 
} 

我在第一context.SaveChanges没问题。但是,当我尝试添加b2相同ACode和参考我得到

违反PRIMARY KEY约束'PK_dbo.As'。不能在对象'dbo.As'中插入重复键。重复的键值是(A0)。

我真的很困惑的是这样做,我会很高兴,如果有人可以解释为什么在第二次调用context.SaveChanges(),EF试图插入而不是使用现有的一个新的A实体。

非常感谢您的帮助

+0

第一次SaveChanges后,A有一个Id值。因为你在第二次调用中隐式添加了相同的对象,所以你会得到异常。您应该保持上下文打开或将A的状态设置为已修改。 – DevilSuichiro

+0

A没有ID,密钥应该是代码。每当我想将实体B添加到数据库时,我都无法拥有相同的上下文。我希望能够随时引用实体B,而不仅仅是当我将实体A插入数据库时​​。 – Teamol

+0

第二个上下文对'a'没有理解,它假定应该加上'a',因此是例外。 –

回答

1

所以感谢王中王的评论,我发现了两件事情。

首先是我可以自动查找外键,如果只有外部标识被分配(不参考)。

var b2 = new B(); 
b2.Name = "B Name 2"; 
b2.ACode = a.Code; 

代替

var b2 = new B(); 
b2.Name = "B Name 2"; 
b2.ACode = a.Code; 
b2.A = a; 

其次是,当你指定参考你要附加的引用对象使用context.As.Attach的(a)之前context.Bs.Add(B2);

非常感谢王国王你的帖子帮助了我很多。