Entity Framework .Remove () a .DeleteObject ()


Odpowiedzi:


275

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 SaveChangesNULLwartość 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ą).


2
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:

Warto zauważyć, że ustawienie .State = EntityState.Deleted nie powoduje automatycznie wykrytej zmiany. ( archiwum )


4
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ą.
Matas Vaitkevicius
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.