Excluir em cascataCascade Delete

A Exclusão em cascata é geralmente usada na terminologia de banco de dados para descrever uma característica que permite a exclusão de uma linha para disparar automaticamente a exclusão de linhas relacionadas.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. Um conceito relacionado também coberto por comportamentos de exclusão de EF Core é a exclusão automática de uma entidade filho quando sua relação com um pai foi desfeita, isso é conhecido como "excluir órfãos".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".

O EF Core implementa vários comportamentos de exclusão diferentes e permite a configuração dos comportamentos de exclusão de relações individuais.EF Core implements several different delete behaviors and allows for the configuration of the delete behaviors of individual relationships. O EF Core também implementa convenções que configuram automaticamente os comportamentos de exclusão padrão úteis para cada relação com base nas exigências do relacionamento.EF Core also implements conventions that automatically configure useful default delete behaviors for each relationship based on the requiredness of the relationship.

Comportamentos de exclusãoDelete behaviors

Os comportamentos de exclusão são definidos no tipo de enumerador DeleteBehavior e pode ser passado para a API fluente OnDelete para controlar se a exclusão de uma entidade de segurança/pai ou o corte da relação com entidades dependentes/filho deve ter um efeito colateral nas entidades dependentes/filho.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.

Há três ações que o EF pode executar quando uma entidade de segurança/pai é excluída ou a relação com o filho é desligada:There are three actions EF can take when a principal/parent entity is deleted or the relationship to the child is severed:

  • O filho/dependente pode ser excluídoThe child/dependent can be deleted
  • Os valores de chave estrangeira do filho podem ser definidos como nuloThe child's foreign key values can be set to null
  • O filho permanece inalteradoThe child remains unchanged

Observação

O comportamento de exclusão configurado no modelo do EF Core só é aplicado quando a entidade de segurança é excluída usando o EF Core e as entidades dependentes são carregadas na memória (ou seja, para dependentes controlados).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). Um comportamento em cascata correspondente precisa ser configurado no banco de dados para garantir que não esteja sendo controlado pelo contexto e tenha a ação necessária aplicada.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. Se você usar o EF Core para criar o banco de dados, esse comportamento em cascata será configurado para você.If you use EF Core to create the database, this cascade behavior will be setup for you.

Para a segunda ação acima, definir um valor de chave estrangeira como nulo não será válido se a chave estrangeira não for anulável.For the second action above, setting a foreign key value to null is not valid if foreign key is not nullable. (Uma chave estrangeira não anulável é equivalente a uma relação obrigatória). Nesses casos, o Core EF controla se a propriedade de chave estrangeira foi marcada como nula até SaveChanges ser chamado, o momento em que uma exceção será gerada porque as alterações não podem ser mantidas no banco de dados.(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. Isso é semelhante a obter uma violação de restrição do banco de dados.This is similar to getting a constraint violation from the database.

Há quatro comportamentos de exclusão, conforme o listado nas tabelas a seguir.There are four delete behaviors, as listed in the tables below.

Relações opcionaisOptional relationships

Para relações opcionais (chave estrangeira anulável), é possível salvar um valor de chave estrangeiro nulo, que resulta nos seguintes efeitos:For optional relationships (nullable foreign key) it is possible to save a null foreign key value, which results in the following effects:

Nome do comportamentoBehavior Name Efeito em dependente/filho na memóriaEffect on dependent/child in memory Efeito em dependente/filho no banco de dadosEffect on dependent/child in database
CascataCascade As entidades são excluídasEntities are deleted As entidades são excluídasEntities are deleted
ClientSetNull (padrão)ClientSetNull (Default) Propriedades de chave estrangeira são definidas como nulasForeign key properties are set to null NenhumNone
SetNullSetNull Propriedades de chave estrangeira são definidas como nulasForeign key properties are set to null Propriedades de chave estrangeira são definidas como nulasForeign key properties are set to null
RestrictRestrict NenhumNone NenhumNone

Relações necessáriasRequired relationships

Para relações obrigatórias (chave estrangeira não anulável), não pode salvar um valor de chave estrangeiro nulo, que resulta nos seguintes efeitos:For required relationships (non-nullable foreign key) it is not possible to save a null foreign key value, which results in the following effects:

Nome do comportamentoBehavior Name Efeito em dependente/filho na memóriaEffect on dependent/child in memory Efeito em dependente/filho no banco de dadosEffect on dependent/child in database
Cascata (Padrão)Cascade (Default) As entidades são excluídasEntities are deleted As entidades são excluídasEntities are deleted
ClientSetNullClientSetNull SaveChanges geraSaveChanges throws NenhumNone
SetNullSetNull SaveChanges geraSaveChanges throws SaveChanges geraSaveChanges throws
RestrictRestrict NenhumNone NenhumNone

Nas tabelas acima, Nenhum pode resultar em uma violação de restrição.In the tables above, None can result in a constraint violation. Por exemplo, se uma entidade de segurança/filho for excluída, mas nenhuma ação for tomada para alterar a chave estrangeira de um dependente/filho, então o banco de dados provavelmente gerará SaveChanges devido a uma violação de restrição de chave estrangeira.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.

Em um alto nível:At a high level:

  • Se você tiver entidades que não podem existir sem um pai, e você deseja que o EF cuide para excluir os filhos automaticamente, use 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.
    • As entidades que não podem existir sem um pai geralmente usam as relações obrigatórias, para as quais Cascade é o padrão.Entities that cannot exist without a parent usually make use of required relationships, for which Cascade is the default.
  • Se você tiver entidades que podem ou não ter um pai, e deseja que o EF cuide de anular a chave estrangeira para você, use ClientSetNullIf 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
    • As entidades que podem existir sem um pai geralmente usam as relações opcionais, para as quais ClientSetNull é o padrão.Entities that can exist without a parent usually make use of optional relationships, for which ClientSetNull is the default.
    • Se você quiser que o banco de dados também tente propagar os valores nulos para chaves estrangeiras filho até mesmo quando a entidade filho não está carregada, em seguida, use 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. No entanto, observe que o banco de dados deve oferecer suporte a isso e configurar o banco de dados assim pode resultar em outras restrições, que, na prática, geralmente tornam essa opção impraticável.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. É por isso que SetNull não é o padrão.This is why SetNull is not the default.
  • Se você não quiser que o EF Core exclua uma entidade automaticamente ou anule automaticamente a chave estrangeira, use Restrict.If you don't want EF Core to ever delete an entity automatically or null out the foreign key automatically, then use Restrict. Observe que isso requer que seu código mantenha entidades filho e seus valores de chave estrangeira em sincronia manualmente, caso contrário, as exceções de restrição serão geradas.Note that this requires that your code keep child entities and their foreign key values in sync manually otherwise constraint exceptions will be thrown.

Observação

No EF Core, ao contrário de EF6, os efeitos em cascata não ocorrem imediatamente, apenas quando SaveChanges é chamado.In EF Core, unlike EF6, cascading effects do not happen immediately, but instead only when SaveChanges is called.

Observação

Alterações no EF Core 2.0: em versões anteriores, Restrict causaria as propriedades de chave estrangeira opcionais em entidades dependentes controladas serem definidas como nulas e o padrão era o comportamento de exclusão para relações opcionais.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. No EF Core 2.0, o ClientSetNull foi introduzido para representar esse comportamento e tornou-se o padrão para relações opcionais.In EF Core 2.0, the ClientSetNull was introduced to represent that behavior and became the default for optional relationships. O comportamento de Restrict foi ajustado para nunca ter efeitos colaterais em entidades dependentes.The behavior of Restrict was adjusted to never have any side effects on dependent entities.

Exemplos de exclusão de entidadeEntity deletion examples

O código a seguir faz parte de um exemplo que pode ser baixado e executado.The code below is part of a sample that can be downloaded and run. O exemplo mostra o que acontece para cada comportamento de exclusão para relações obrigatórias e opcionais quando uma entidade pai é excluída.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)}");
}

Vamos examinar cada variação para entender o que está acontecendo.Let's walk through each variation to understand what is happening.

DeleteBehavior.Cascade com relação obrigatória ou opcionalDeleteBehavior.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.
  • O blog está marcado como ExcluídoBlog is marked as Deleted
  • As postagens inicialmente permanecem inalteradas porque cascatas não acontecem até SaveChangesPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • SaveChanges envia exclusões para dependentes/filhos (postagens) e, em seguida, a entidade de segurança/pai (blog)SaveChanges sends deletes for both dependents/children (posts) and then the principal/parent (blog)
  • Depois de salvar, todas as entidades serão desanexadas porque agora foram excluídas do banco de dadosAfter saving, all entities are detached since they have now been deleted from the database

DeleteBehavior.ClientSetNull ou DeleteBehavior.SetNull com relação obrigatóriaDeleteBehavior.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.
  • O blog está marcado como ExcluídoBlog is marked as Deleted
  • As postagens inicialmente permanecem inalteradas porque cascatas não acontecem até SaveChangesPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • SaveChanges tenta definir a postagem FK como nula, mas falha porque a FK não é anulávelSaveChanges attempts to set the post FK to null, but this fails because the FK is not nullable

DeleteBehavior.ClientSetNull ou DeleteBehavior.SetNull com relação opcionalDeleteBehavior.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.
  • O blog está marcado como ExcluídoBlog is marked as Deleted
  • As postagens inicialmente permanecem inalteradas porque cascatas não acontecem até SaveChangesPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • SaveChanges tenta definir FK de filhos/dependentes (postagens) como nulo antes de excluir a entidade de segurança/pai (blog)SaveChanges attempts sets the FK of both dependents/children (posts) to null before deleting the principal/parent (blog)
  • Depois de salvar, a entidade de segurança/pai (blog) será excluída, mas os seus dependentes/filhos (postagens) ainda são controladosAfter saving, the principal/parent (blog) is deleted, but the dependents/children (posts) are still tracked
  • Os dependentes/filhos controlados (postagens) agora têm valores FK nulos e sua referência para a entidade de segurança/pai excluída (blog) foi removidaThe tracked dependents/children (posts) now have null FK values and their reference to the deleted principal/parent (blog) has been removed

DeleteBehavior.Restrict com relação obrigatória ou opcionalDeleteBehavior.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.
  • O blog está marcado como ExcluídoBlog is marked as Deleted
  • As postagens inicialmente permanecem inalteradas porque cascatas não acontecem até SaveChangesPosts initially remain Unchanged since cascades do not happen until SaveChanges
  • Como Restrict informa ao EF para não definir automaticamente o FK como nulo, ele permanece não nulo e SaveChanges é gerada sem salvarSince Restrict tells EF to not automatically set the FK to null, it remains non-null and SaveChanges throws without saving

Exemplos de exclusão de órfãosDelete orphans examples

O código a seguir faz parte de um exemplo que pode ser baixado e executado.The code below is part of a sample that can be downloaded and run. O exemplo mostra o que acontece para cada comportamento de exclusão de relações obrigatórias e opcionais quando a relação entre um pai/entidade de segurança e seus filhos/dependentes for desfeita.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. Neste exemplo, a relação é desfeita removendo os dependentes/filhos (postagens) da propriedade de navegação da coleção na entidade de segurança/pai (blog).In this example, the relationship is severed by removing the dependents/children (posts) from the collection navigation property on the principal/parent (blog). No entanto, o comportamento é o mesmo se a referência de dependente/filho a entidade de segurança/pai em vez disso for anulada.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)}");
}

Vamos examinar cada variação para entender o que está acontecendo.Let's walk through each variation to understand what is happening.

DeleteBehavior.Cascade com relação obrigatória ou opcionalDeleteBehavior.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.
  • As postagens são marcadas como modificadas porque cortar a relação fez o FK ser marcado como nuloPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • Se o FK não for anulável, o valor real não mudará mesmo que ele esteja marcado como nuloIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • SaveChanges envia exclusões para dependentes/filhos (postagens)SaveChanges sends deletes for dependents/children (posts)
  • Depois de salvar, os dependentes/filhos (postagens) serão desanexados porque agora foram excluídos do banco de dadosAfter saving, the dependents/children (posts) are detached since they have now been deleted from the database

DeleteBehavior.ClientSetNull ou DeleteBehavior.SetNull com relação obrigatóriaDeleteBehavior.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.
  • As postagens são marcadas como modificadas porque cortar a relação fez o FK ser marcado como nuloPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • Se o FK não for anulável, o valor real não mudará mesmo que ele esteja marcado como nuloIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • SaveChanges tenta definir a postagem FK como nula, mas falha porque a FK não é anulávelSaveChanges attempts to set the post FK to null, but this fails because the FK is not nullable

DeleteBehavior.ClientSetNull ou DeleteBehavior.SetNull com relação opcionalDeleteBehavior.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.
  • As postagens são marcadas como modificadas porque cortar a relação fez o FK ser marcado como nuloPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • Se o FK não for anulável, o valor real não mudará mesmo que ele esteja marcado como nuloIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • SaveChanges define FK de filhos/dependentes (postagens) como nuloSaveChanges sets the FK of both dependents/children (posts) to null
  • Depois de salvar, os dependentes/filhos (postagens) agora têm valores FK nulos e sua referência para a entidade de segurança/pai excluída (blog) foi removidaAfter saving, the dependents/children (posts) now have null FK values and their reference to the deleted principal/parent (blog) has been removed

DeleteBehavior.Restrict com relação obrigatória ou opcionalDeleteBehavior.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.
  • As postagens são marcadas como modificadas porque cortar a relação fez o FK ser marcado como nuloPosts are marked as Modified because severing the relationship caused the FK to be marked as null
    • Se o FK não for anulável, o valor real não mudará mesmo que ele esteja marcado como nuloIf the FK is not nullable, then the actual value will not change even though it is marked as null
  • Como Restrict informa ao EF para não definir automaticamente o FK como nulo, ele permanece não nulo e SaveChanges é gerada sem salvarSince Restrict tells EF to not automatically set the FK to null, it remains non-null and SaveChanges throws without saving

Em cascata para entidades sem controleCascading to untracked entities

Quando você chama SaveChanges, as regras de exclusão em cascata serão aplicadas a qualquer entidade que está sendo controlada pelo contexto.When you call SaveChanges, the cascade delete rules will be applied to any entities that are being tracked by the context. Esta é a situação em todos os exemplos mostrados acima, que é por que o SQL foi gerado para excluir a entidade de segurança/pai (blog) e todos os seus dependentes/filhos (postagens):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

Se apenas a entidade de segurança for carregada, por exemplo, quando uma consulta for feita para um blog sem um Include(b => b.Posts) para incluir também as postagens, SaveChanges apenas gerará o SQL para excluir a entidade de segurança/pai: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

Os dependentes/filhos (postagens) só serão excluídos se o banco de dados tiver um comportamento em cascata correspondente configurado.The dependents/children (posts) will only be deleted if the database has a corresponding cascade behavior configured. Se você usar o EF para criar o banco de dados, esse comportamento em cascata será configurado para você.If you use EF to create the database, this cascade behavior will be setup for you.