連鎖削除Cascade Delete

連鎖削除は、一般的に使用されているデータベース用語です。関連する行の削除を自動的にトリガーするための、行の削除を可能にする特性を示します。Cascade delete is commonly used in database terminology to describe a characteristic that allows the deletion of a row to automatically trigger the deletion of related rows. EF Core の削除動作にも含まれる密接に関連した概念として、親エンティティとのリレーションシップが切断されたときの子エンティティの自動削除があります。これは一般に "孤立の削除" と呼ばれます。A closely related concept also covered by EF Core delete behaviors is the automatic deletion of a child entity when it's relationship to a parent has been severed--this is commonly known as "deleting orphans".

EF Core は複数の削除動作を実装しており、個々のリレーションシップの削除動作を構成できます。EF Core implements several different delete behaviors and allows for the configuration of the delete behaviors of individual relationships. また、EF Core はリレーションシップの必要性に基づいて、各リレーションシップに対して有用な既定の削除動作を自動的に構成する規則も実装しています。EF Core also implements conventions that automatically configure useful default delete behaviors for each relationship based on the requiredness of the relationship.

削除動作Delete behaviors

削除動作は、DeleteBehavior 列挙子型で定義されます。また、OnDelete fluent API に渡して、プリンシパル/親エンティティの削除または依存/子エンティティとのリレーションシップの切断が、依存/子エンティティに副作用を及ぼすかどうかを制御することができます。Delete behaviors are defined in the DeleteBehavior enumerator type and can be passed to the OnDelete fluent API to control whether the deletion of a principal/parent entity or the severing of the relationship to dependent/child entities should have a side effect on the dependent/child entities.

プリンシパル/親エンティティが削除されたとき、またはその子とのリレーションシップが切断されたときに EF が実行する可能性があるアクションは次の 3 つです。There are three actions EF can take when a principal/parent entity is deleted or the relationship to the child is severed:

  • 子/依存が削除される可能性がありますThe child/dependent can be deleted
  • 子の外部キー (FK) 値が null に設定される可能性がありますThe child's foreign key values can be set to null
  • 子は変更されませんThe child remains unchanged

注意

EF Core モデルに構成されている削除動作は、EF Core を使用してプリンシパル エンティティが削除され、依存エンティティがメモリ内に読み込まれている場合 (つまり、追跡されている依存エンティティの場合) にのみ適用されます。The delete behavior configured in the EF Core model is only applied when the principal entity is deleted using EF Core and the dependent entities are loaded in memory (that is, for tracked dependents). 対応する連鎖動作をデータベースに設定し、コンテキストによって追跡されていないデータに対して必要なアクションが適用されるようにする必要があります。A corresponding cascade behavior needs to be setup in the database to ensure data that is not being tracked by the context has the necessary action applied. EF Core を使用してデータベースを作成すると、この連鎖動作が設定されます。If you use EF Core to create the database, this cascade behavior will be setup for you.

上記の 2 番目のアクションで、外部キーが Null 許容でない場合、外部キー値を null に設定する操作は無効になります For the second action above, setting a foreign key value to null is not valid if foreign key is not nullable. (Null 許容ではない外部キーは、必須のリレーションシップと同等です)。このような場合、EF Core は、SaveChanges が呼び出されるまで外部キーのプロパティが null とマークされていたことを追跡します。このとき、変更をデータベースに永続化できないため、例外がスローされます。(A non-nullable foreign key is equivalent to a required relationship.) In these cases, EF Core tracks that the foreign key property has been marked as null until SaveChanges is called, at which time an exception is thrown because the change cannot be persisted to the database. これは、データベースから制約違反を受け取る場合と似ています。This is similar to getting a constraint violation from the database.

次の表に示すように、削除動作は 4 つあります。There are four delete behaviors, as listed in the tables below.

省略可能なリレーションシップOptional relationships

省略可能なリレーションシップ (Null 許容の外部キー) の場合、null の外部キー値を保存することが_できます_。その結果、次のような影響があります。For optional relationships (nullable foreign key) it is possible to save a null foreign key value, which results in the following effects:

動作名Behavior Name メモリ内の依存/子への影響Effect on dependent/child in memory データベース内の依存/子への影響Effect on dependent/child in database
CascadeCascade エンティティは削除されますEntities are deleted エンティティは削除されますEntities are deleted
ClientSetNull (既定)ClientSetNull (Default) 外部キー プロパティは null に設定されますForeign key properties are set to null なしNone
SetNullSetNull 外部キー プロパティは null に設定されますForeign key properties are set to null 外部キー プロパティは null に設定されますForeign key properties are set to null
RestrictRestrict なしNone なしNone

必須リレーションシップRequired relationships

必須のリレーションシップ (Null 許容ではない外部キー) の場合、null の外部キー値を保存することが_できません_。その結果、次のような影響があります。For required relationships (non-nullable foreign key) it is not possible to save a null foreign key value, which results in the following effects:

動作名Behavior Name メモリ内の依存/子への影響Effect on dependent/child in memory データベース内の依存/子への影響Effect on dependent/child in database
Cascade (既定)Cascade (Default) エンティティは削除されますEntities are deleted エンティティは削除されますEntities are deleted
ClientSetNullClientSetNull SaveChanges がスローされますSaveChanges throws なしNone
SetNullSetNull SaveChanges がスローされますSaveChanges throws SaveChanges がスローされますSaveChanges throws
RestrictRestrict なしNone なしNone

上記の表の "なし" は制約違反を引き起こす可能性があります。In the tables above, None can result in a constraint violation. たとえば、プリンシパル/子エンティティが削除されても、依存/子の外部キーを変更するアクションが実行されない場合、データベースは外部制約違反のために SaveChanges をスローする可能性があります。For example, if a principal/child entity is deleted but no action is taken to change the foreign key of a dependent/child, then the database will likely throw on SaveChanges due to a foreign constraint violation.

高レベルでは:At a high level:

  • 親なしでは存在できないエンティティがあり、EF で子を自動的に削除したい場合は、Cascade を使用します。If you have entities that cannot exist without a parent, and you want EF to take care for deleting the children automatically, then use Cascade.
    • 通常、親なしでは存在できないエンティティは、必須のリレーションシップを使用します。この場合、Cascade が既定です。Entities that cannot exist without a parent usually make use of required relationships, for which Cascade is the default.
  • エンティティが親を持つ場合と持たない場合があり、EF で外部キーを自動機に null にする場合は、ClientSetNull を使用します。If you have entities that may or may not have a parent, and you want EF to take care of nulling out the foreign key for you, then use ClientSetNull
    • 通常、親なしでは存在できるエンティティは、省略可能なリレーションシップを使用します。この場合、ClientSetNull が既定です。Entities that can exist without a parent usually make use of optional relationships, for which ClientSetNull is the default.
    • 子エンティティが読み込まれていない場合でも、データベースで null 値が子外部キーに伝達されるようにするには、SetNull を使用します。If you want the database to also try to propagate null values to child foreign keys even when the child entity is not loaded, then use SetNull. ただし、データベースがこれをサポートしている必要があります。また、このようにデータベースを構成すると、他の制限が生じる可能性があります。そのため、多くの場合、実際にはこのオプションは実用的ではありません。However, note that the database must support this, and configuring the database like this can result in other restrictions, which in practice often makes this option impractical. これが SetNull が既定ではない理由です。This is why SetNull is not the default.
  • エンティティの削除や外部キーを null にする処理を EF Core で自動実行しないようにするには、Restrict を使用します。If you don't want EF Core to ever delete an entity automatically or null out the foreign key automatically, then use Restrict. この場合、コードで子エンティティとその外部キー値を手動で継続的に同期させる必要があります。そうしないと、制約の例外がスローされます。Note that this requires that your code keep child entities and their foreign key values in sync manually otherwise constraint exceptions will be thrown.

注意

EF Core は EF6 とは異なり、連鎖の影響はすぐに発生するのではなく、SaveChanges が呼び出されたときにのみ発生します。In EF Core, unlike EF6, cascading effects do not happen immediately, but instead only when SaveChanges is called.

注意

EF Core 2.0 の変更点: 以前のリリースでは、Restrict を使用すると、追跡されている依存エンティティの省略可能な外部キーのプロパティが null に設定されていました。これは、省略可能なリレーションシップの既定の削除動作でした。Changes in EF Core 2.0: In previous releases, Restrict would cause optional foreign key properties in tracked dependent entities to be set to null, and was the default delete behavior for optional relationships. EF Core 2.0 では、その動作を表す ClientSetNull が導入され、省略可能なリレーションシップの既定になりました。In EF Core 2.0, the ClientSetNull was introduced to represent that behavior and became the default for optional relationships. Restrict の動作は、依存エンティティに対する副作用がないように調整されました。The behavior of Restrict was adjusted to never have any side effects on dependent entities.

エンティティ削除の例Entity deletion examples

以下のコードは、ダウンロードして実行できるサンプルの一部です。The code below is part of a sample that can be downloaded and run. このサンプルは、親エンティティが削除されたときに、省略可能なリレーションシップと必須のリレーションシップのそれぞれの削除動作で、何が起こるかを示しています。The sample shows what happens for each delete behavior for both optional and required relationships when a parent entity is deleted.

var blog = context.Blogs.Include(b => b.Posts).First();
var posts = blog.Posts.ToList();

DumpEntities("  After loading entities:", context, blog, posts);

context.Remove(blog);

DumpEntities($"  After deleting blog '{blog.BlogId}':", context, blog, posts);

try
{
    Console.WriteLine();
    Console.WriteLine("  Saving changes:");

    context.SaveChanges();

    DumpSql();

    DumpEntities("  After SaveChanges:", context, blog, posts);
}
catch (Exception e)
{
    DumpSql();

    Console.WriteLine();
    Console.WriteLine($"  SaveChanges threw {e.GetType().Name}: {(e is DbUpdateException ? e.InnerException.Message : e.Message)}");
}

各動作のサンプルを見て、何が起こるかを理解しましょう。Let's walk through each variation to understand what is happening.

必須または省略可能なリレーションシップがある DeleteBehavior.CascadeDeleteBehavior.Cascade with required or optional relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After deleting blog '1':
    Blog '1' is in state Deleted with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  Saving changes:
    DELETE FROM [Posts] WHERE [PostId] = 1
    DELETE FROM [Posts] WHERE [PostId] = 2
    DELETE FROM [Blogs] WHERE [BlogId] = 1

  After SaveChanges:
    Blog '1' is in state Detached with 2 posts referenced.
      Post '1' is in state Detached with FK '1' and no reference to a blog.
      Post '2' is in state Detached with FK '1' and no reference to a blog.
  • ブログは Deleted とマークされていますBlog is marked as Deleted
  • SaveChanges まで連鎖が発生しないため、初期段階で投稿は Unchanged のままですPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • SaveChanges は、両方の依存/子 (投稿) の削除、次にプリンシパル/親 (ブログ) の削除を送信します。SaveChanges sends deletes for both dependents/children (posts) and then the principal/parent (blog)
  • 保存後、すべてのエンティティは、データベースから削除されているのでデタッチされますAfter saving, all entities are detached since they have now been deleted from the database

必須のリレーションシップがある DeleteBehavior.ClientSetNull または DeleteBehavior.SetNullDeleteBehavior.ClientSetNull or DeleteBehavior.SetNull with required relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After deleting blog '1':
    Blog '1' is in state Deleted with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  Saving changes:
    UPDATE [Posts] SET [BlogId] = NULL WHERE [PostId] = 1

  SaveChanges threw DbUpdateException: Cannot insert the value NULL into column 'BlogId', table 'EFSaving.CascadeDelete.dbo.Posts'; column does not allow nulls. UPDATE fails. The statement has been terminated.
  • ブログは Deleted とマークされていますBlog is marked as Deleted
  • SaveChanges まで連鎖が発生しないため、初期段階で投稿は Unchanged のままですPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • SaveChanges は投稿 FK を null に設定しようとしますが、FK が Null 許容ではないため失敗しますSaveChanges attempts to set the post FK to null, but this fails because the FK is not nullable

省略可能なリレーションシップがある DeleteBehavior.ClientSetNull または DeleteBehavior.SetNullDeleteBehavior.ClientSetNull or DeleteBehavior.SetNull with optional relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After deleting blog '1':
    Blog '1' is in state Deleted with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  Saving changes:
    UPDATE [Posts] SET [BlogId] = NULL WHERE [PostId] = 1
    UPDATE [Posts] SET [BlogId] = NULL WHERE [PostId] = 2
    DELETE FROM [Blogs] WHERE [BlogId] = 1

  After SaveChanges:
    Blog '1' is in state Detached with 2 posts referenced.
      Post '1' is in state Unchanged with FK 'null' and no reference to a blog.
      Post '2' is in state Unchanged with FK 'null' and no reference to a blog.
  • ブログは Deleted とマークされていますBlog is marked as Deleted
  • SaveChanges まで連鎖が発生しないため、初期段階で投稿は Unchanged のままですPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • SaveChanges は、プリンシパル/親 (ブログ) を削除する前に、依存/子 (投稿) 両方の FK を null に設定しますSaveChanges attempts sets the FK of both dependents/children (posts) to null before deleting the principal/parent (blog)
  • 保存後、プリンシパル/親 (ブログ) は削除されますが、依存/子 (投稿) は引き続き追跡されますAfter saving, the principal/parent (blog) is deleted, but the dependents/children (posts) are still tracked
  • 追跡されている依存/子 (投稿) には null の FK 値があり、削除されたプリンシパル/親 (ブログ) への参照は削除されましたThe tracked dependents/children (posts) now have null FK values and their reference to the deleted principal/parent (blog) has been removed

必須または省略可能なリレーションシップがある DeleteBehavior.RestrictDeleteBehavior.Restrict with required or optional relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After deleting blog '1':
    Blog '1' is in state Deleted with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  Saving changes:
  SaveChanges threw InvalidOperationException: The association between entity types 'Blog' and 'Post' has been severed but the foreign key for this relationship cannot be set to null. If the dependent entity should be deleted, then setup the relationship to use cascade deletes.
  • ブログは Deleted とマークされていますBlog is marked as Deleted
  • SaveChanges まで連鎖が発生しないため、初期段階で投稿は Unchanged のままですPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • Restrict は、EF に対して FK を自動的に null に設定しないように指示しますが、Null 許容ではないままなので、SaveChanges は保存せずに例外をスローしますSince Restrict tells EF to not automatically set the FK to null, it remains non-null and SaveChanges throws without saving

孤立の削除例Delete orphans examples

以下のコードは、ダウンロードして実行できるサンプルの一部です。The code below is part of a sample that can be downloaded and run. このサンプルは、親/プリンシパルとその子/依存のリレーションシップが切断されたときに、省略可能なリレーションシップと必須のリレーションシップのそれぞれの削除動作で何が起こるかを示しています。The sample shows what happens for each delete behavior for both optional and required relationships when the relationship between a parent/principal and its children/dependents is severed. この例では、プリンシパル/親 (ブログ) のコレクション ナビゲーション プロパティから依存/子 (投稿) を削除することで、リレーションシップが切断されています。In this example, the relationship is severed by removing the dependents/children (posts) from the collection navigation property on the principal/parent (blog). ただし、依存/子からプリンシパル/親への参照が null に設定される場合、動作は同じです。However, the behavior is the same if the reference from dependent/child to principal/parent is instead nulled out.

var blog = context.Blogs.Include(b => b.Posts).First();
var posts = blog.Posts.ToList();

DumpEntities("  After loading entities:", context, blog, posts);

blog.Posts.Clear();

DumpEntities("  After making posts orphans:", context, blog, posts);

try
{
    Console.WriteLine();
    Console.WriteLine("  Saving changes:");

    context.SaveChanges();

    DumpSql();

    DumpEntities("  After SaveChanges:", context, blog, posts);
}
catch (Exception e)
{
    DumpSql();

    Console.WriteLine();
    Console.WriteLine($"  SaveChanges threw {e.GetType().Name}: {(e is DbUpdateException ? e.InnerException.Message : e.Message)}");
}

各動作のサンプルを見て、何が起こるかを理解しましょう。Let's walk through each variation to understand what is happening.

必須または省略可能なリレーションシップがある DeleteBehavior.CascadeDeleteBehavior.Cascade with required or optional relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After making posts orphans:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Modified with FK '1' and no reference to a blog.
      Post '2' is in state Modified with FK '1' and no reference to a blog.

  Saving changes:
    DELETE FROM [Posts] WHERE [PostId] = 1
    DELETE FROM [Posts] WHERE [PostId] = 2

  After SaveChanges:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Detached with FK '1' and no reference to a blog.
      Post '2' is in state Detached with FK '1' and no reference to a blog.
  • リレーションシップを切断すると FK は null とマークされるので、投稿は Modified とマークされますPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • FK が Null 許容でない場合、null とマークされていても実際の値は変更されませんIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • SaveChanges は依存/子 (投稿) の削除を送信しますSaveChanges sends deletes for dependents/children (posts)
  • 保存後、依存/子 (投稿) はデータベースから削除されているので、デタッチされますAfter saving, the dependents/children (posts) are detached since they have now been deleted from the database

必須のリレーションシップがある DeleteBehavior.ClientSetNull または DeleteBehavior.SetNullDeleteBehavior.ClientSetNull or DeleteBehavior.SetNull with required relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After making posts orphans:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Modified with FK 'null' and no reference to a blog.
      Post '2' is in state Modified with FK 'null' and no reference to a blog.

  Saving changes:
    UPDATE [Posts] SET [BlogId] = NULL WHERE [PostId] = 1

  SaveChanges threw DbUpdateException: Cannot insert the value NULL into column 'BlogId', table 'EFSaving.CascadeDelete.dbo.Posts'; column does not allow nulls. UPDATE fails. The statement has been terminated.
  • リレーションシップを切断すると FK は null とマークされるので、投稿は Modified とマークされますPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • FK が Null 許容でない場合、null とマークされていても実際の値は変更されませんIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • SaveChanges は投稿 FK を null に設定しようとしますが、FK が Null 許容ではないため失敗しますSaveChanges attempts to set the post FK to null, but this fails because the FK is not nullable

省略可能なリレーションシップがある DeleteBehavior.ClientSetNull または DeleteBehavior.SetNullDeleteBehavior.ClientSetNull or DeleteBehavior.SetNull with optional relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After making posts orphans:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Modified with FK 'null' and no reference to a blog.
      Post '2' is in state Modified with FK 'null' and no reference to a blog.

  Saving changes:
    UPDATE [Posts] SET [BlogId] = NULL WHERE [PostId] = 1
    UPDATE [Posts] SET [BlogId] = NULL WHERE [PostId] = 2

  After SaveChanges:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK 'null' and no reference to a blog.
      Post '2' is in state Unchanged with FK 'null' and no reference to a blog.
  • リレーションシップを切断すると FK は null とマークされるので、投稿は Modified とマークされますPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • FK が Null 許容でない場合、null とマークされていても実際の値は変更されませんIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • SaveChanges は、両方の依存/子 (投稿) の FK を null に設定しますSaveChanges sets the FK of both dependents/children (posts) to null
  • 保存後、依存/子 (投稿) には null の FK 値があり、削除されたプリンシパル/親 (ブログ) への参照は削除されましたAfter saving, the dependents/children (posts) now have null FK values and their reference to the deleted principal/parent (blog) has been removed

必須または省略可能なリレーションシップがある DeleteBehavior.RestrictDeleteBehavior.Restrict with required or optional relationship

  After loading entities:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
      Post '2' is in state Unchanged with FK '1' and reference to blog '1'.

  After making posts orphans:
    Blog '1' is in state Unchanged with 2 posts referenced.
      Post '1' is in state Modified with FK '1' and no reference to a blog.
      Post '2' is in state Modified with FK '1' and no reference to a blog.

  Saving changes:
  SaveChanges threw InvalidOperationException: The association between entity types 'Blog' and 'Post' has been severed but the foreign key for this relationship cannot be set to null. If the dependent entity should be deleted, then setup the relationship to use cascade deletes.
  • リレーションシップを切断すると FK は null とマークされるので、投稿は Modified とマークされますPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • FK が Null 許容でない場合、null とマークされていても実際の値は変更されませんIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • Restrict は、EF に対して FK を自動的に null に設定しないように指示しますが、Null 許容ではないままなので、SaveChanges は保存せずに例外をスローしますSince Restrict tells EF to not automatically set the FK to null, it remains non-null and SaveChanges throws without saving

追跡されていないエンティティに対する連鎖Cascading to untracked entities

SaveChanges を呼び出すと、コンテキストによっては、追跡されているすべてのエンティティに連鎖削除ルールが適用されます。When you call SaveChanges, the cascade delete rules will be applied to any entities that are being tracked by the context. これは上記のすべての例で起こる状況です。プリンシパル/親 (ブログ) とすべての依存/子 (投稿) の両方を削除する SQL を生成したのは、このためです。This is the situation in all the examples shown above, which is why SQL was generated to delete both the principal/parent (blog) and all the dependents/children (posts):

    DELETE FROM [Posts] WHERE [PostId] = 1
    DELETE FROM [Posts] WHERE [PostId] = 2
    DELETE FROM [Blogs] WHERE [BlogId] = 1

プリンシパルのみが読み込まれている場合 (たとえば、投稿に Include(b => b.Posts) がないブログに対してクエリが実行された場合など) にのみ、SaveChanges はプリンシパル/親を削除する SQL を生成します。If only the principal is loaded--for example, when a query is made for a blog without an Include(b => b.Posts) to also include posts--then SaveChanges will only generate SQL to delete the principal/parent:

    DELETE FROM [Blogs] WHERE [BlogId] = 1

データベースに対応する連鎖動作が構成されている場合にのみ、依存者/子 (投稿) は削除されます。The dependents/children (posts) will only be deleted if the database has a corresponding cascade behavior configured. EF を使用してデータベースを作成すると、この連鎖動作が設定されます。If you use EF to create the database, this cascade behavior will be setup for you.