我有两个实体RelayConfig和StandardContact之间的多对多关系
实体:
public class RelayConfig : EntityBase, IDataErrorInfo {
...
//Associations
public virtual ICollection<StandardContact> StandardContacts { get; set; }
}
public class StandardContact :EntityBase, IDataErrorInfo {
...
//Associations
public virtual ICollection<RelayConfig> RelayConfigs { get; set; }
}
现在我正在尝试更新 RelayConfig 及其与 StandardContact 的关系。这是更新 RelayConfig 的代码。
public class RelayConfigRepository : GenericRepository<RelayConfig> {
....
public void Update(RelayConfig relayConfig, List<StandardContact> addedContacts, List<StandardContact> deletedContacts) {
context.RelayConfigs.Add(relayConfig);
if (relayConfig.Id > 0) {
context.Entry(relayConfig).State = EntityState.Modified;
}
addedContacts.ForEach(ad => relayConfig.StandardContacts.Add(ad));
foreach (StandardContact standardContact in relayConfig.StandardContacts) {
if (standardContact.Id > 0) {
context.Entry(standardContact).State = EntityState.Modified;
}
}
relayConfig.StandardContacts.ToList().ForEach(s => {
if (deletedContacts.Any(ds => ds.Id == s.Id)) {
context.Entry(s).State = EntityState.Deleted;
}
});
}
...
}
当我运行更新时,我得到了异常,其内部异常如下所示。
InnerException: System.Data.SqlClient.SqlException
Message=Violation of PRIMARY KEY constraint 'PK__Standard__EE33D91D1A14E395'. Cannot insert duplicate key in object 'dbo.StandardContactRelayConfigs'.
dbo.StandardContactRelayConfigs 是链接 RelayConfig 和 StandardContact 的链接表。如您所见,如果 Id > 0,更新代码会将所有实体更改为修改状态(更新方法末尾设置的已删除记录除外)。
我真的不明白为什么实体框架试图在链接表中插入行并且由于上述异常而失败。我已经将现有 RelayConfig.StandardContacts 实体的 EntityState 更改为 Modified。
简而言之,为什么我会在上面粘贴异常。
问候,尼尔文。
编辑: 上面更新方法的参数(addedContacts 和 deletedContacts)已经是 Id > 0 的现有实体。
Edit2: 根据您的建议,我从更新方法中删除了用于插入新(数据库中不存在)记录的代码。所以现在我的更新方法只将现有的 StandardContact 记录添加到 RelayConfig 集合。但我仍然无法让代码正常工作。首先是我正在使用的代码
public void Update(RelayConfig relayConfig, List<StandardContact> addedContacts, List<StandardContact> deletedContacts) {
context.RelayConfigs.Add(relayConfig);
if (relayConfig.Id > 0) {
context.Entry(relayConfig).State = EntityState.Modified;
}
addedContacts.ForEach(contact => {
context.StandardContacts.Attach(contact);
relayConfig.StandardContacts.Add(contact);
objectContext.ObjectStateManager.
ChangeRelationshipState(relayConfig, contact, rs => rs.StandardContacts, EntityState.Added);
});
}
现在我只专注于添加记录。当 StandardContact(联系人变量)与任何其他现有 RelayConfig 对象没有任何关系时,上述代码运行良好。在这种情况下,将为添加到 RelayConfig.StandardContacts 集合的每个联系人在联结表中创建一个新条目。但是,当 StandardContact(联系人变量)已经与其他 RelayConfig 对象有关系时,事情会变得很糟糕(不可预测的行为)。在这种情况下,当 StandardContact 添加到 RelayConfig.StandardContacts 集合时,StandardContact 也会添加到数据库中,从而创建重复条目。不仅如此,还创建了一个新的 RelayConfig 对象(我不知道从哪里开始)并插入到 RelayConfigs 表中。
@Ladislav,如果您有一些适用于多对多关系更新(用于分离实体)的示例代码,那么我可以要求您向我展示相同的代码。
问候, 尼尔文
Edit3(解决方案):
最终我最终使用了一种完全不同的方法。这是更新的代码
public void Update(RelayConfig relayConfig, List<StandardContact> exposedContacts) {
context.Entry(relayConfig).State = EntityState.Modified;
relayConfig.StandardContacts.Clear();
exposedContacts.ForEach(exposedContact => {
StandardContact exposedContactEntity = null;
exposedContactEntity = context.StandardContacts.SingleOrDefault(sc => sc.Id == exposedContact.Id);
if (exposedContactEntity != null) {
relayConfig.StandardContacts.Add(exposedContactEntity);
}
});
}
问候,尼尔文。