我有以下StandardContact實體框架更新許多一對多的關係 - POCO
實體兩個實體RelayConfig和之間的許多一對多的關係:
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。
總之,爲什麼我會得到上面粘貼的異常。
關於, Nirvan。
編輯: 到更新上述(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,如果你有一些適用於多對多關係更新(對於分離的實體)的示例代碼,那麼我可以請求你請讓我看到同樣的內容。
問候, NIRVAN
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);
}
});
}
關於, Nirvan。
感謝您的回覆。但我仍然有疑問。讓我們假設沒有addedRecords或deletedRecords。假設一個RelayConfig有兩個StandardContact記錄,並且我想將這些更改保存到這兩個StandardContact記錄中,除了將它們的EntityState更改爲已修改之外,是否還必須更改這兩個StandardContacts的RelationshipState?我的意思是我們如何更新關係的多方面(忽略現在添加和刪除的記錄)。 – Jatin 2012-04-23 11:10:04
如果添加realayConfig,則必須將關係狀態更改爲未更改。如果你只是Attache realayConfig,你不必對這些關係做任何事情,但當你想添加新的關係時,附加可能會導致另一個問題。 – 2012-04-23 11:14:17
請看我的編輯標記爲Edit2: – Jatin 2012-04-24 05:22:13