实体框架似乎在父对象之前保存子对象

问题描述:

我使用的是实体框架6.2,代码优先。我有以下两类:实体框架似乎在父对象之前保存子对象

public class Agent 
    { 
     [Key] 
     [DatabaseGenerated(DatabaseGeneratedOption.None)] 
     public int? AgentId { get; set; } 
     public string FirstName { get; set; } 
     public string Surname { get; set; } 
     public int OfficeId { get; set; } 
     [ForeignKey("OfficeId")] 
     public virtual Office Office { get; set; }   
    } 

public class Office 
    { 
     [Key] 
     [DatabaseGenerated(DatabaseGeneratedOption.None)] 
     public int OfficeId { get; set; } 
     public string Agency { get; set; } 
     public string Branch { get; set; } 
     [InverseProperty("Office")] 
     public virtual ICollection<Agent> Agents { get; set; } 
    } 

所以每个代理都属于一个办公室(且只有一个办公室)。相反,办公室可以包含许多代理。

我的应用程序连接到一个Web API,该API用代理和办公室为其提供XML数据(为此,我使用XDocument)。然后用这些对象填充我的DbContext,并调用dbContext.SaveChanges();

在这一点上,我得到这个错误:

"Cannot add or update a child row: a foreign key constraint fails (fusion . agent , CONSTRAINT FK_agent_office_OfficeId FOREIGN KEY (OfficeId) REFERENCES office (OfficeId) ON DELETE CASCADE ON UPDATE CASCADE)"

像EF试图在办公室之前保存代理声音给我。所以当它将第一个代理写入数据库时​​,就没有相应的办公室,事务就失败了。我会想象EF会找出事物的正确顺序(基于导航属性),并按正确的顺序保存东西?

现在,我需要指出的是,当我的应用程序将代理和​​办公室添加到DbContext中时,它首先添加代理,然后添加代理 - 这也许是EF为什么还将它们插入到数据库中相同的顺序。不幸的是,当我的应用程序调用Web API时,API会先向我发送带有代理的XML数据,然后再向我发送办公室数据。

如何让EF在代理商之前保存办公室?

+0

如果Agent表引用了Office表的主键,则EF将首先创建Office行,以便将其ID插入到新的Agent行中。 EF不仅可以查看导航属性,还可以从数据库映射中推断出它们是如何导出的。 –

+0

您可以将代码添加到上下文中吗? – Mats391

+0

当你想添加新的“代理和办公室”或者当你想添加一个代理时,你有这个问题吗? –

EF确实根据导航属性计算出正确的顺序。还有其他的错误。有几件事可能是这个问题。

你为什么用[DatabaseGenerated(DatabaseGeneratedOption.None)]?你正在创建和维护ID还是数据库?如果它的数据库不想要[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

代理上的一个可为空的主键?那是对的吗?主键不能/不应该为空...

您不需要设置[InverseProperty("Office")]为正常的1对多关系。这可能会令EF令人困惑。

+0

谢谢Gareth,您的回复指出我的方向是正确的 – user1900799