私は2つのエンティティRelayConfigと間の多対多の関係を次のようしているStandardContact多対多の関係を更新するエンティティフレームワーク - POCO
エンティティ:今
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; }
}
I 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の場合(Updateメソッドの最後に削除されたレコードを除く)、Updateコードはすべてのエンティティを変更された状態に変更します。
エンティティ・フレームワークがリンクされた表に行を挿入しようとしているのに、上記の例外が発生して失敗している理由を理解できません。私はすでに、既存のRelayConfig.StandardContactsエンティティのEntityStateをModifiedに変更します。
要するに、上記の例外を貼り付ける理由は何ですか?
について、 Nirvan。
編集: (addedContactsとdeletedContacts)上記の方法を更新するためのパラメータが既にID> 0
EDIT2を持つエンティティ存在している:私は新鮮挿入するためのコードを削除し、あなたの提案を1として( をデータベースに存在しない)レコードを更新メソッドから取得します。だから私の更新メソッドは、既存の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(contact変数)が他の既存の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に2つのStandardContactレコードがあり、これらの2つのStandardContactレコードに変更を永続化したい場合、EntityStateを変更するだけでなく、これらの2つのStandardContactのRelationshipStateを変更する必要がありますか?私は関係の多方面をどのように更新するのですか(今は追加されたレコードと削除されたレコードを無視する)。 – Jatin
realayConfigを追加する場合は、関係状態を変更しないで変更する必要があります。あなたがAttay realayConfigだけであれば、それらの関係で何もする必要はありませんが、新しい関係を追加したい場合には、添付すると別の問題が発生する可能性があります。 –
Edit2と記された編集をご覧ください。 – Jatin