Je kunt een item uit een database verwijderen met EF door de volgende twee methoden te gebruiken.
De eerste staat op de EntityCollection
en de tweede op de ObjectContext
.
Wanneer moet elk worden gebruikt?
Heeft de ene de voorkeur boven de andere?
Remove()
retourneert een bool
en DeleteObject()
retourneert void
.
Antwoord 1, autoriteit 100%
Het is over het algemeen niet correct dat u met beide methoden “een item uit een database kunt verwijderen“. Om precies te zijn is het zo:
-
ObjectContext.DeleteObject(entity)
markeert de entiteit alsDeleted
in de context. (Het isEntityState
is daarnaDeleted
.) Als je daarnaSaveChanges
aanroept, stuurt EF een SQL-statementDELETE
naar de databank. Als er geen referentiële beperkingen in de database worden geschonden, wordt de entiteit verwijderd, anders wordt er een uitzondering gegenereerd. -
EntityCollection.Remove(childEntity)
markeert de relatie tussen ouder enchildEntity
alsDeleted
. Als dechildEntity
zelf uit de database wordt verwijderd en wat er precies gebeurt als jeSaveChanges
aanroept, hangt af van het soort relatie tussen de twee:-
Als de relatie optioneelis, dwz dat de externe sleutel die van het kind naar de ouder in de database verwijst,
NULL
-waarden toestaat, wordt deze buitenlandse sleutel ingesteld naar null en als uSaveChanges
aanroept, wordt dezeNULL
-waarde voor dechildEntity
naar de database geschreven (dwz de relatie tussen de twee wordt verwijderd) . Dit gebeurt met een SQLUPDATE
-instructie. Er vindt geenDELETE
-instructie plaats. -
Als de relatie vereistis (de FK staat geen
NULL
-waarden toe) en de relatie is niet identificerend(wat betekent dat de refererende sleutel geen deel uitmaakt van de (samengestelde) primaire sleutel van het kind) u moet het kind toevoegen aan een andere ouder of u moet het kind expliciet verwijderen (metDeleteObject
dan). Als je dit niet doet, wordt een referentiële beperking geschonden en EF zal een uitzondering genereren wanneer jeSaveChanges
aanroept – de beruchte “De relatie kan niet worden gewijzigd omdat een of meer van de buitenlandse- sleuteleigenschappen is niet-nullable“uitzondering of vergelijkbaar. -
Als de relatie identificerendis (het is noodzakelijkerwijs vereist, omdat geen enkel deel van de primaire sleutel
NULL
kan zijn) zal EF markeer dechildEntity
ook alsDeleted
. Als uSaveChanges
aanroept, wordt een SQLDELETE
-instructie naar de database verzonden. Als er geen andere referentiële beperkingen in de database worden geschonden, wordt de entiteit verwijderd, anders wordt er een uitzondering gegenereerd.
-
Ik ben eigenlijk een beetje in de war over het gedeelte Opmerkingen op de MSDN-paginaje hebt gelinkt omdat er staat: “Als de relatie een referentiële integriteitsbeperking heeft, markeert het aanroepen van de Remove-methode op een afhankelijk object zowel de relatie als het afhankelijke object voor verwijdering.“. Dit lijkt mij onnauwkeurig of zelfs verkeerd omdat alle drie bovenstaande gevallen een “referentiële integriteitsbeperking” hebben, maar alleen in het laatste geval wordt het kind daadwerkelijk verwijderd. (Tenzij ze met “afhankelijk object” een object bedoelen dat deelneemt aan een identificerende relatie, wat echter een ongebruikelijke terminologie zou zijn.)
Antwoord 2, autoriteit 5%
Als je Deleted echt wilt gebruiken, moet je je externe sleutels nullable maken, maar dan krijg je verweesde records (wat een van de belangrijkste redenen is waarom je dat in eerste instantie niet zou moeten doen plaats). Gebruik dus gewoon Remove()
ObjectContext.DeleteObject(entity)markeert de entiteit als Verwijderd in de context. (Daarna wordt EntityState verwijderd.) Als je daarna SaveChanges aanroept, stuurt EF een SQL DELETE-statement naar de database. Als er geen referentiële beperkingen in de database worden geschonden, wordt de entiteit verwijderd, anders wordt er een uitzondering gegenereerd.
EntityCollection.Remove(childEntity)markeert de relatie tussen ouder en childEntity als verwijderd. Als de childEntity zelf uit de database wordt verwijderd en wat er precies gebeurt als u SaveChanges aanroept, hangt af van het soort relatie tussen de twee:
Het vermelden waard is dat het instellen van .State = EntityState.Deleted
triggert niet automatisch gedetecteerde wijziging.(archief)