Diferença entre DbSet.Remove e DbContext.Entry (entity) .State = EntityState.Deleted
Considere o seguinte modelo de entidade:
public class Agreement : Entity
{
public int AgreementId { get; set; }
public virtual ICollection<Participant> Participants { get; set; }
}
public class Establishment : Entity
{
public int EstablishmentId { get; set; }
}
public class Participant : Entity
{
public int AgreementId { get; set; }
public virtual Agreement Agreement { get; set; }
public int EstablishmentId { get; set; }
public virtual Establishment { get; set; }
public bool IsOwner { get; set; }
}
A razão não há uma diretaICollection<Establishment>
na entidade Contrato é devido à propriedade IsOwner, que define ainda mais esse relacionamento muitos-para-muitos.
O relacionamento é mapeado da seguinte forma:
internal ParticipantOrm()
{
ToTable(typeof(Participant).Name);
HasKey(k => new { k.AgreementId, k.EstablishmentId });
HasRequired(d => d.Agreement)
.WithMany(p => p.Participants)
.HasForeignKey(d => d.AgreementId)
.WillCascadeOnDelete(true);
HasRequired(d => d.Establishment)
.WithMany()
.HasForeignKey(d => d.EstablishmentId)
.WillCascadeOnDelete(true);
}
O relacionamento é unidirecional, o que significa que você só pode chegar aos Participantes de dentro de um Acordo - você não pode acessar os acordos do Estabelecimento.
Agora, como a chave primária da entidade do Acordo faz parte da chave primária do participante gerúndio, e como a exclusão em cascata é especificada, esperaria que colocar o Contrato no estado Excluído também faria com que cada entidade na coleção de Participantes também fosse colocada na estado excluído.
Isso parece funcionar ao chamar Remover em um Acordo DbSet:
// this works
dbContext.Agreements.Remove(agreement);
dbContext.SaveChanges();
No entanto, não parece funcionar quando simplesmente definindo o estado da entrada de acordo para excluído:
// this causes an exception when Participants is not empty
dbContext.Entry(agreement).State = EntityState.Deleted;
dbContext.SaveChanges();
Existe uma maneira de definir o relacionamento de modo que simplesmente colocar a entidade do Contrato no estado excluído também faça com que as entidades do item de coleta correspondentes sejam colocadas no estado excluído?
Atualizar
Eu tenho lido sobre isso e descobri que ansioso carregar a coleção de participantes não ajuda:
// eager loading does not help, this still breaks
var agreement = dbContext.Set<Agreement>()
.Include(a => a.Participants)
.FirstOrDefault();
dbContext.Entry(agreement).State = EntityState.Deleted;
dbContext.SaveChanges();