web-dev-qa-db-ja.com

エンティティフレームワーク.Remove()と.DeleteObject()

次の2つの方法を使用してEFを使用してデータベースから項目を削除できます。

1つ目はEntityCollection、2つ目はObjectContextです。

それぞれをいつ使うべきですか?

一方が他方よりも好まれていますか?

Remove()boolを返し、DeleteObject()voidを返します。

137
Sam Leach

両方の方法で "アイテムをデータベースから削除する"ことができるのは、一般的に正しくありません。正確に言うと、

  • ObjectContext.DeleteObject(entity)は、コンテキスト内でエンティティをDeletedname __としてマークします。 (EntityStatename__はその後のDeletedname__です。)その後にSaveChangesname__を呼び出すと、EFはSQLのDELETEname__ステートメントをデータベースに送信します。データベース内の参照制約に違反していない場合は、エンティティは削除されます。それ以外の場合は、例外がスローされます。

  • EntityCollection.Remove(childEntity)は、parentとchildEntityname__の関係をDeletedname __としてマークします。 childEntityname__自体がデータベースから削除され、SaveChangesname__を呼び出したときに実際に何が起こるかは、2つの間の関係の種類によって異なります。

    • 関係がoptionalの場合、つまりデータベース内の子から親への外部キーでNULLname__値を使用できる場合、この外部キーはnullに設定されます。 SaveChangesname__に対するNULLname__のこのchildEntityname__値は、データベースに書き込まれます(つまり、2つの関係は削除されます)。これはSQLのUPDATEname__ステートメントで起こります。 DELETEname__ステートメントは発生しません。

    • 関係がrequired(FKがNULLname__値を許可しない)で、関係がnot識別(の場合)つまり、外部キーは子の(複合)主キーの一部ではありません)子を別の親に追加するか、子を明示的に削除する必要があります(DeleteObjectthenを使用)。これらを行わないと、参照制約に違反し、SaveChangesname__を呼び出したときにEFが例外をスローします - 悪名高い " 関係が変更されなかったのは、外部キーのプロパティはnullを許容しない "例外など。

    • 関係が識別の場合(必然的にrequiredの場合、主キーのどの部分もNULLname__にすることはできないため)EF childEntityname__をDeletedname__としてもマークします。 SaveChangesname__を呼び出すと、SQLのDELETEname__ステートメントがデータベースに送信されます。データベース内の他の参照制約に違反していなければ、そのエンティティは削除されます。そうでなければ、例外がスローされます。

私は実際には少し混乱しています MSDNページのRemarksセクション リンクしています: "リレーションシップに参照整合性制約がある場合は、Removeメソッドを呼び出します。依存オブジェクトは関係と依存オブジェクトの両方を削除対象としてマーク付けします "#:。上記の3つのケースはすべて "参照整合性制約"を持っていますが、実際には子が実際に削除される場合に限り、これは不正確であるかさらには間違っているようです。 ( "従属オブジェクト"で識別されている関係に参加しているオブジェクトを意味しているのであれば、それは珍しい用語ですが)

269
Slauma

本当にDeletedを使いたいのであれば、あなたはあなたの外部キーをnullにすることができるようにしなければならないでしょう、しかし、あなたは孤立したレコードになってしまいます。 Remove()を使うだけです

ObjectContext.DeleteObject(entity) は、コンテキスト内でエンティティを削除済みとしてマークします。 (その後、EntityStateは削除されます。)後でSaveChangesを呼び出すと、EFはSQL DELETEステートメントをデータベースに送信します。データベース内の参照制約に違反していない場合は、エンティティは削除されます。それ以外の場合は、例外がスローされます。

EntityCollection.Remove(childEntity) は、parentとchildEntityの関係を削除済みとしてマークします。 childEntity自体がデータベースから削除され、SaveChangesを呼び出したときに実際に何が起こるかは、2つの間の関係の種類によって異なります。

注目に値するのは、.State = EntityState.Deletedを設定しても自動的に検出された変更が行われないことです。archive

13