Generalnie nie jest poprawne, że można „ usunąć element z bazy danych ” za pomocą obu metod. A dokładniej jest tak:
ObjectContext.DeleteObject(entity)oznacza jednostkę jakoDeleted w kontekście. (To EntityStatejest Deletedpo tym.) Jeśli wywołasz SaveChangespóźniej, EF wysyła DELETEinstrukcję SQL do bazy danych. Jeśli nie zostaną naruszone żadne ograniczenia referencyjne w bazie danych, jednostka zostanie usunięta, w przeciwnym razie zostanie zgłoszony wyjątek.
EntityCollection.Remove(childEntity)oznacza związek między rodzicem a childEntityjakoDeleted . Jeśli childEntitysamo zostanie usunięte z bazy danych i to, co dokładnie się stanie, gdy zadzwonisz, SaveChangeszależy od rodzaju relacji między nimi:
Jeśli relacja jest opcjonalna , tj. Klucz obcy, który odwołuje się od dziecka do rodzica w bazie danych zezwala na NULLwartości, ten obcy zostanie ustawiony na null i jeśli wywołasz SaveChangestę NULLwartość dla, childEntityzostanie zapisany w bazie danych (tj. Relacja między oba są usuwane). Dzieje się tak w przypadku UPDATEinstrukcji SQL . Żadne DELETEstwierdzenie nie występuje.
Jeśli relacja jest wymagana (FK nie zezwala na NULLwartości), a relacja nie identyfikuje (co oznacza, że klucz obcy nie jest częścią (złożonego) klucza podstawowego dziecka), musisz albo dodać dziecko do innego rodzica, albo musisz jawnie usunąć dziecko ( DeleteObjectwtedy). Jeśli nie wykonasz żadnej z tych czynności, ograniczenie referencyjne zostanie naruszone, a EF zgłosi wyjątek podczas wywołania SaveChanges- niesławny „ Nie można zmienić relacji, ponieważ co najmniej jedna właściwość klucza obcego nie dopuszcza wartości null ” lub podobny.
Jeżeli związek jest identyfikowanie (nie jest to koniecznie wymagane wtedy, ponieważ każda część klucza podstawowego nie może być NULL) będzie EF zaznaczyć childEntity, jak Deletedrównież. W przypadku wywołania instrukcji SaveChangesSQL DELETEzostanie wysłana do bazy danych. Jeśli żadne inne ograniczenia referencyjne w bazie danych nie są naruszone, jednostka zostanie usunięta, w przeciwnym razie zostanie zgłoszony wyjątek.
W rzeczywistości jestem trochę zdezorientowany co do sekcji Uwagi na stronie MSDN, do której zostało utworzone łącze , ponieważ jest napisane: „ Jeśli relacja ma ograniczenie integralności referencyjnej, wywołanie metody Remove na obiekcie zależnym oznacza zarówno relację, jak i obiekt zależny do usunięcia. ”. Wydaje mi się to nieprecyzyjne lub nawet błędne, ponieważ wszystkie trzy powyższe przypadki mają „ więzową integralność ”, ale tylko w ostatnim przypadku dziecko jest faktycznie usuwane. (Chyba że mają na myśli „ obiekt zależny ” obiekt, który uczestniczy w relacji identyfikującej, która byłaby jednak niezwykłą terminologią).
Więzy integralności wikipedia: Więzy integralności to właściwość danych, która po spełnieniu wymaga, aby każda wartość jednego atrybutu (kolumny) relacji (tabeli) istniała jako wartość innego atrybutu w innej (lub tej samej) relacji (tabela ), więc gdy relacja jest opcjonalna, łamiemy regułę integralności danych
Mohammadreza
3
@Mohammadreza: Jeśli interpretujesz NULLjako „Nie jest wartością” (zamiast „wartości NULL”, jak pisałem, czasami trochę niedbale), to „opcjonalna relacja” nie stoi w sprzeczności z definicją integralności referencyjnej.
Slauma,
1
Więc jaka jest wersja EF Core ObjectContext.DeleteObject?
Jonathan Allen
13
Jeśli naprawdę chcesz użyć Deleted, musisz uczynić twoje klucze obce zerowymi, ale wtedy skończysz z osieroconymi rekordami (co jest jednym z głównych powodów, dla których nie powinieneś tego robić). Więc po prostu użyjRemove()
ObjectContext.DeleteObject (jednostka) oznacza jednostkę jako usuniętą w kontekście. (Po tym EntityState zostanie usunięty.) Jeśli wywołasz SaveChanges później EF wysyła instrukcję SQL DELETE do bazy danych. Jeśli nie zostaną naruszone żadne ograniczenia referencyjne w bazie danych, jednostka zostanie usunięta, w przeciwnym razie zostanie zgłoszony wyjątek.
EntityCollection.Remove (childEntity) oznacza relację między rodzicem a childEntity jako usuniętą. Jeśli samo childEntity zostanie usunięte z bazy danych i to, co dokładnie się stanie, gdy wywołasz SaveChanges, zależy od rodzaju relacji między nimi:
Ok, dla tych, którzy odrzucają moją odpowiedź, nie ma to nic wspólnego z odpowiedzią Slaumy - obaj wskazują na tę samą dokumentację . Mój wyjaśnia przykłady z życia, podczas gdy jego teoria jest ich częścią.
NULL
jako „Nie jest wartością” (zamiast „wartościNULL
”, jak pisałem, czasami trochę niedbale), to „opcjonalna relacja” nie stoi w sprzeczności z definicją integralności referencyjnej.ObjectContext.DeleteObject
?Jeśli naprawdę chcesz użyć Deleted, musisz uczynić twoje klucze obce zerowymi, ale wtedy skończysz z osieroconymi rekordami (co jest jednym z głównych powodów, dla których nie powinieneś tego robić). Więc po prostu użyj
Remove()
ObjectContext.DeleteObject (jednostka) oznacza jednostkę jako usuniętą w kontekście. (Po tym EntityState zostanie usunięty.) Jeśli wywołasz SaveChanges później EF wysyła instrukcję SQL DELETE do bazy danych. Jeśli nie zostaną naruszone żadne ograniczenia referencyjne w bazie danych, jednostka zostanie usunięta, w przeciwnym razie zostanie zgłoszony wyjątek.
EntityCollection.Remove (childEntity) oznacza relację między rodzicem a childEntity jako usuniętą. Jeśli samo childEntity zostanie usunięte z bazy danych i to, co dokładnie się stanie, gdy wywołasz SaveChanges, zależy od rodzaju relacji między nimi:
Warto zauważyć, że ustawienie
.State = EntityState.Deleted
nie powoduje automatycznie wykrytej zmiany. ( archiwum )źródło