web-dev-qa-db-ja.com

Entity Frameworkによるカスケード削除-EFによって削除された関連エンティティ

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

私のデザイン:

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

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

これは私のモデルのようになります:

関係には、次のデフォルト以外の設定があります。

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

関係EntityTypeA -> EntityTypeBにはOnDelete: 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

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

質問

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

29
Nitramk

これは、EFでカスケード削除が動作する方法とまったく同じです。 EFデザイナーのリレーションにCascadeを設定すると、読み込まれた実現エンティティごとにDELETEステートメントを実行するようにEFに指示されます。 ON CASCADE DELETEデータベース内。

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

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

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

41
Ladislav Mrnka

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

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

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

enter image description here

これについてはブログで詳しく説明します。 Entity Framework Cascading Deletes; Set it from the database。

5
ΩmegaMan