29

Entity Framework での削除に問題があります。つまり、データベースでカスケード削除を使用するように EF を明示的に構成したにもかかわらず、EF は明示的にデータベースからエンティティを削除しようとします。

私のデザイン:

MainEntity、およびの 3 つのエンティティ タイプがEntityTypeAありEntityTypeBます。EntityTypeAEF は、 および を削除するときにカスケード削除を使用するように構成されていますEntityTypeB。つまり、 のインスタンスを削除するとMainEntity、関連するEntityTypeAおよびEntityTypeBインスタンスもすべて削除されます。親を削除せずに、EntityTypeAまたは削除することはありません。EntityTypeB

私の問題は、EF が に対して明示的にDELETEステートメントを発行しEntityTypeA、アプリケーションがクラッシュすることです。

これは私のモデルがどのように見えるかです:

リレーションには、次のデフォルト以外の構成があります。

  • MainEntity -> EntityTypeA OnDelete: Cascade
  • MainEntity -> EntityTypeB OnDelete: Cascade

関係EntityTypeA -> EntityTypeBOnDelete: None

データベースの内容

INSERT INTO MainEntities (Name) values ('Test')
insert into EntityTypeA (MainEntityID) VALUES (1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)

私のコード:

class Program
{
   static void Main(string[] args)
   {
      var context = new Model1Container();
      var mainEntity = context.MainEntities.Include("EntityTypeA").SingleOrDefault();
      context.DeleteObject(mainEntity);
      context.SaveChanges();
   }
}

何が起こるのですか

SaveChanges を呼び出すと、Entity Framework はデータベースで次の処理を実行します。

exec sp_executesql N'delete [dbo].[EntityTypeA]
where ([Id] = @0)',N'@0 int',@0=1

EntityTypeB のテーブルに EntityTypeA インスタンスを参照する項目があるため、これにより外部キー違反が発生します。

質問

カスケード削除を使用するように Entity Framework を構成したにもかかわらず、Entity Framework が EntityTypeA のインスタンスに対して明示的な削除を発行するのはなぜですか? Include("EntityTypeA") を削除すると、再び機能し始めます。

4

2 に答える 2

41

これは、カスケード削除がEFでどのように動作するかを正確に示しています。EF Designerでリレーションにカスケードを設定するとDELETE、ロードされた実現エンティティごとにステートメントを実行するようにEFに指示されます。ON CASCADE DELETEデータベースには何も書かれていません。

EFを使用するときにカスケード削除を設定するには、次の2つの手順が必要です。

  • EFデザイナーでカスケードをリレーションに設定します。これは、ロードされたすべての関連エンティティを、親エンティティを削除する前に削除する必要があることをコンテキストに指示します。これが発生しない場合、EFは例外をスローします。これは、内部状態が、ロードされた子が既存の親エンティティに関連していないことを検出するためです。親エンティティのdeleteステートメントの実行前と実行後のどちらで発生するかはわかりませんが、違いはありません。EFは、変更の実行後に関連するエンティティをリロードしないため、データベースでトリガーされたカスケード削除については認識しません。
  • ON CASCADE DELETEデータベースのリレーションに設定します。これにより、親の削除時にコンテキストにロードされなかったすべての関連レコードを削除するようにSQLに指示されます。

EFでのカスケード削除の実装は奇妙で非常に非効率的ですが、これが動作方法であり、使用する場合は、このシナリオで正しく動作するようにアプリケーションを変更する必要があります。

于 2011-03-27T11:13:16.057 に答える
5

EF デザイナーの代わりに、データベースの FK 制約にカスケード削除を設定することもできます。

カスケード削除を設定する方法に関する Sql Server Management Studio (SSMS) からの視覚的な手順を次に示します。

完了したら、削除を試みる前にデータベースに対してedmxを更新することを忘れないでください。

ここに画像の説明を入力

これについては、私のブログで詳しく説明しています: Entity Framework Cascading Deletes; データベースから設定します。

于 2015-05-28T14:41:44.397 に答える