web-dev-qa-db-ja.com

EntityCollection Clear()およびRemove()メソッド

EFエンティティのすべてのコレクションアイテムを削除する正しい方法は何ですか?以下のコードでは、DocumentItemsはドキュメントに関連するドキュメントアイテムのコレクションです。このコードはClear()で続行されますが、関連アイテムがFKを介してドキュメントに接続されており、FKが必須であるため、SaveChanges()では失敗します。したがって、Clear()の後に外部キーがないと、どういうわけか空中に浮かんでいると思います。

各アイテムでRemove()を呼び出すコレクションのforeachループでこれを解決しますか、それとも別の方法がありますか?

// remove existing document items to prepare for refreshing them
existing.DocumentItems.Clear();
// adds new Document Items
PrepareInvoice(existing, collection);
_repository.SaveChanges();
14
mare

これは、コレクション内のアイテムを削除する1つの方法です。

VB

TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))

C#

TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))

次に、電話する必要があります

ctx.SaveChanges()
13
Brian Rizo

Clearは参照を削除するだけで、全体を削除するわけではありません。

あなたの状況では

existing.DocumentItems.Clear();  

EntitySet内のすべてのDocumentItemはクリアされますが、データベースで削除しようとした場合と同じように、実際のDocumentItemを削除/削除するか、失敗してコミットする必要があります。

参照をデタッチするループをループしてから、削除するエンティティを削除する必要があります(null許容であり、状況によってはそうでない場合を除く)


あるいは、clearとAssociationChangedHandlerを使用して古いオブジェクトを自動的に削除する実装を見てきました。基本的に、変更が「削除/削除」の場合、孤立したオブジェクトに対してDeleteObject()を呼び出します。

11
Nix

トリック:親と子の関係を設定するときは、子に「複合」キーを作成する必要があります。このように、親に1つまたはすべての子を削除するように指示すると、関連するレコードが実際にデータベースから削除されます。

Fluent APIを使用して複合キーを構成するには:

modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });

次に、関連する子を削除するには:

var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);

var childToRemove = parent.Children.First(); // Change the logic 
parent.Children.Remove(childToRemove);

// or, you can delete all children 
// parent.Children.Clear();

_context.SaveChanges();

完了!

2
Mosh

ええ、1歳ですが、ちょっとした注意点があります... DeleteObjectはラムダ式の引数と同じ型の1つのパラメーターを受け取るため、次のものを使用できます。

entityCollection.ToList().ForEach(ctx.DeleteObject);

VBが同様の構文をサポートしているかどうかはわかりませんが、誰か?

1
Dave Parker

答えへのNixコメントに答えるためだけに、

entityCollection.Clearメソッドと同様に、EntityCollection.Removeメソッドは、エンティティではなく、関係の削除のみをマークしているように見えます。

ドキュメントには、エンティティにも削除のマークが付けられると記載されていることは知っていますが、私のテストでは、説明した動作があります(誰でも理由を説明できますか?)。

したがって、概念モデルに1対多の外部キー制約がある場合、コンテキストへの変更を永続ストアに保存することはできません。

私が見つけた唯一の方法は(CascadeDeleteをしたくないので)、子をループし、それぞれでcontext.DeleteObjectを呼び出して、エンティティと関連する関係を削除することです。

0
ilmatte