Estrutura de entidade .Remove () vs. .DeleteObject ()

Respostas:

275

Geralmente, não é correto que você possa " remover um item de um banco de dados " com os dois métodos. Para ser mais preciso, é assim:

  • ObjectContext.DeleteObject(entity)marca a entidade comoDeleted no contexto. (É EntityStateé Deleteddepois disso.) Se você ligar SaveChangesdepois EF envia um SQL DELETEdeclaração para o banco de dados. Se nenhuma restrição referencial no banco de dados for violada, a entidade será excluída, caso contrário, uma exceção será lançada.

  • EntityCollection.Remove(childEntity)marca o relacionamento entre pai e childEntitycomoDeleted . Se o childEntitypróprio for excluído do banco de dados e o que exatamente acontece quando você ligar, SaveChangesdepende do tipo de relacionamento entre os dois:

    • Se o relacionamento for opcional , ou seja, a chave estrangeira que se refere do filho ao pai no banco de dados permitir NULLvalores, esse valor será definido como nulo e se você chamar SaveChangesesse NULLvalor, o valor childEntityserá gravado no banco de dados (ou seja, o relacionamento entre os dois são removidos). Isso acontece com uma UPDATEinstrução SQL . Nenhuma DELETEdeclaração ocorre.

    • Se o relacionamento for necessário (o FK não permite NULLvalores) e o relacionamento não estiver sendo identificado (o que significa que a chave estrangeira não faz parte da chave primária (composta) da criança), você deverá adicionar a criança a outro pai ou mãe. você deve excluir explicitamente o filho (com DeleteObjectisso). Se você não fizer nada disso, a restrição de referência será violada e a EF emitirá uma exceção quando você chamar SaveChanges- a infame " A relação não pôde ser alterada porque uma ou mais propriedades da chave estrangeira não podem ser nulas " ou semelhante.

    • Se o relacionamento é identificar (é necessariamente necessário , em seguida, porque qualquer parte da chave primária não pode ser NULL) EF irá marcar o childEntitytão Deletedbem. Se você chamar, SaveChangesuma DELETEinstrução SQL será enviada ao banco de dados. Se nenhuma outra restrição referencial no banco de dados for violada, a entidade será excluída, caso contrário, uma exceção será lançada.

Na verdade, estou um pouco confuso sobre a seção Comentários na página do MSDN que você vinculou porque diz: " Se o relacionamento tiver uma restrição de integridade referencial, chamar o método Remove em um objeto dependente marca tanto o relacionamento quanto o objeto dependente para exclusão. " Isso me parece impreciso ou até errado, porque os três casos acima têm uma " restrição de integridade referencial ", mas apenas no último caso a criança é de fato excluída. (A menos que eles signifiquem com " objeto dependente ", um objeto que participe de um relacionamento de identificação que seria uma terminologia incomum.)

Slauma
fonte
2
Wikipedia: Integridade referencial: Integridade referencial é uma propriedade de dados que, quando satisfeita, exige que todo valor de um atributo (coluna) de uma relação (tabela) exista como valor de outro atributo em uma relação diferente (ou a mesma) (tabela ), de modo que quando o relacionamento é opcional que quebrar a integridade dos dados regra
Mohammadreza
3
@ Mohammadreza: Se você interpreta NULLcomo "Não é um valor" (em vez de "o valor NULL", como escrevi às vezes um pouco desleixado), um "relacionamento opcional" não está em contradição com a definição de integridade referencial.
Slauma
1
Então, qual é a versão do EF Core ObjectContext.DeleteObject?
Jonathan Allen
13

Se você realmente deseja usar Deleted, terá que tornar suas chaves estrangeiras anuláveis, mas acabará com registros órfãos (que é um dos principais motivos pelos quais você não deveria fazer isso em primeiro lugar). Então é só usarRemove()

ObjectContext.DeleteObject (entity) marca a entidade como Excluída no contexto. (É EntityState é excluído depois disso.) Se você chamar SaveChanges depois, o EF enviará uma instrução SQL DELETE ao banco de dados. Se nenhuma restrição referencial no banco de dados for violada, a entidade será excluída, caso contrário, uma exceção será lançada.

EntityCollection.Remove (childEntity) marca o relacionamento entre pai e childEntity como Excluído. Se o próprio childEntity for excluído do banco de dados e o que exatamente acontece quando você chama SaveChanges, depende do tipo de relacionamento entre os dois:

Uma coisa que vale a pena notar é que a configuração .State = EntityState.Deleted não aciona alterações detectadas automaticamente. ( arquivo )

Matas Vaitkevicius
fonte
4
Ok, para aqueles que votaram menos na minha resposta, isso não tem nada a ver com o Slauma - ambos apontam para a mesma documentação . O meu explica exemplos da vida real, enquanto sua teoria faz parte disso.
Matas Vaitkevicius 06/04