5

Zmagałem się z EF podczas próby odczytu rekordów, a następnie usunąłem te rekordy w tej samej transakcji. I początkowo stosując metodę EntityState.Deleted, która dałaby błąd:EntityState.Deleted nie działa, czy Remove (entity) to robi?

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

Ale jeśli zmienię go lubić mam poniżej, używając .Wykręcić(), to wszystko jest dobrze.

  1. Jaka jest różnica i najlepsze czasy użycia .Usuń() kontra. Usunięto?
  2. Jak mogę wykonać tę pracę przy użyciu metody .Deleted? Próbowałem utworzyć nowe wystąpienie kontekstu do mojego repozytorium do odczytu i inne do usunięcia, ale następnie dostałem błędy związane z IEntityTracker nie można śledzić wielu wystąpień ... Próbowałem również. Włącz na początku odczytu, aby załadować zależne rekordy do EF, więc wie o nich i usuwa je. Próbowałem też. Najpierw odczytać zapisy odczytu. Wszystko bez skutku.

Oto metoda, o której mowa. Zauważ, że mam rodzajowe repozytorium, które wykorzystuje metodę .Deleted który służył mi dobrze, dopóki tego scenariusza (czytanie następnie usuwając te same rekordy.)

//Delete Allocation Need and AllocatedContainers for alloc need id 
public ActionConfirmation<int> DeleteAllocRecords(int intFacilityId, AllocNeedSourceTypes needSourceType, int intNeedSourceId) 
{ 
var context = new InventoryMgmtContext(); 
var repository = new AllocationNeedRepository(context); 

//Delete Allocation Need and hence children in Allocated Containers 
var srcType = needSourceType.ToString(); 
List<AllocationNeed> allocNeeds = repository.SearchFor(
    x => x.FacilityId == intFacilityId 
    && x.NeedSourceType == srcType 
    && x.NeedSourceId == intNeedSourceId 
).ToList(); 

//var deleteRepository = new Repository<AllocationNeed>(); <--tried separate instance of context to delete...no worky. 

foreach (AllocationNeed allocNeed in allocNeeds) 
{ 
    try 
    { 
     //NO WORK: context.Entry(allocNeed).State = System.Data.EntityState.Deleted; 
     context.AllocationNeeds.Attach(allocNeed); 
     context.AllocationNeeds.Remove(allocNeed); <-- Works 
     context.SaveChanges(); 
    } 
    catch (Exception ex) 
    { 
     return ActionConfirmation<int>.CreateFailureConfirmation(ex.Message, allocNeed.Id); 
    } 
} 

Odpowiedz

6

Remove również usunąć obiekty podrzędne, ale przy użyciu Deleted będzie nie. Powinieneś naprawdę używać Remove właśnie z tego powodu. Jeśli naprawdę chcesz chcesz użyć Deleted, będziesz musiał uczynić swoje obce klucze zerowalnym, ale wtedy skończy Ci się osierocone rekordy (co jest jednym z głównych powodów, dla których powinieneś tego nie robić w pierwszej kolejności).

+0

Nie ma prawdziwego powodu do użycia. Usunięto to, co wiem, poza tym, że już napisałem swoje ogólne repozytorium, aby użyć tej metody, ale jest to jedna linia kodu do zmiany, aby użyć metody .Remove, więc użyję tego . Dzięki! –

+0

Usuń nie usuwa obiektów podrzędnych. Jeśli FK obiektu potomnego jest wartością NULL, ustawi wartość null, jeśli będzie to wymagane, wygeneruje wyjątek. Sposobem usuwania obiektów podrzędnych jest oznaczenie związku jako 'CascadeOnDelete' w kodzie pierwszym lub w db-pierwszym. – Shoe

+0

^-> lub usuń z dołu do góry. – JoeBrockhaus

2

1.) Jaka jest różnica i najlepsze czasy użycia .Usuń() kontra. Usunięto?

Wygląda na to, że ustawienie stanu obiektu na usunięte powoduje, że SaveChanges() usuwa tylko tę konkretną jednostkę z bazy danych, nie biorąc pod uwagę innych wierszy, które mogą się do niej odwoływać za pomocą niepustej kolumny klucza obcego.

Remove() uwzględni wiersze, które są częścią relacji.

2.) Jak mogę wykonać tę pracę przy użyciu metody .Deleted?

Jeśli dla określonego wiersza istnieje zachowanie ON CASCADE DELETE, baza danych powinna obsłużyć je automatycznie. Jest to domyślne zachowanie, gdy pozwalasz EF generować bazę danych.

+0

To jest DB Pierwszy scenariusz, i mam Cascade na kasowanie ustawić w bazie danych i sprawdziłem, że EF wybrał to do w pliku .edmx ... więc wydaje się. Usunięty usunie tylko podany podmiot, a nie żadnych związane z. –

+0

Kiedy mówisz, że usunie tylko określoną jednostkę, masz na myśli kolekcje w pamięci EF lub bazę danych? Czy EF rzuca wyjątek podczas "SaveChanges()"?Jeśli nie ma żadnych wyjątków, EF wyśle ​​usunięcie dla jednostki nadrzędnej, a baza danych całkowicie usunie wszystkie elementy podrzędne, jeśli ustawiono kaskadę. Jednak nie zdziwiłbym się, gdyby kolekcja elementów podrzędnych w pamięci była zsynchronizowana. – JoeBrockhaus