2012-10-02 13 views
8

Próbuję wprowadzić funkcję miękkiego usuwania w moim projekcie, zastępując metodę DbContext.SaveChanges() i cofając usunięcie wszelkich elementów implementujących mój interfejs ISoftDelete.Zastępowanie usunięcia obiektu skojarzeniami

interface ISoftDelete 
{ 
    bool IsDeleted { get; set; } 
} 

W metodzie SaveChanges() Wołam metodę dla każdego wpisu, który jest w 'usunięty' państwa i implementuje ISoftDelete mój SoftDelete().

var entries = this.ChangeTracker.Entries().Where(x => (x.State == EntityState.Deleted) && x.Entity is ISoftDelete) 
        .ToList(); 
       entries.ForEach(SoftDelete); 

Moja SoftDelete() metoda jest następująca:

private void SoftDelete(DbEntityEntry entry) 
{ 
    if (entry.State == EntityState.Deleted && entry.Entity is ISoftDelete) 
    { 
     entry.Reload(); 
     var entity = (ISoftDelete)entry.Entity; 
     entity.IsDeleted = true; 
     entry.State = EntityState.Modified; 
    } 
} 

To zadziała idealnie, dopóki nie natknę się na podmiot, który ma powiązanie jeden do jednego z czymś innym. W którym momencie, jest wyjątek z tego błędu:

{"A relationship from the 'ChildParent' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'Parent' must also in the 'Deleted' state."}

Czy istnieje sposób, aby uzyskać wszystkie stowarzyszenia dla tego podmiotu i zmienić stan usunięty dla nich, jak również?

Próbowałem już uzyskać odniesienie do rzeczywistej jednostki stowarzyszonej, ale jednostka EntityState jest ustawiona na Unchanged zamiast Deleted.

+3

Myślę, że to skojarzenie jest zaznaczone jako usunięte (asocjacje są traktowane jako oddzielne obiekty w EF), ale nie powiązane z nimi. Teraz, gdy EF próbuje usunąć powiązanie, nie może tego zrobić, ponieważ powiązany obiekt nie jest oznaczony jako usunięty. Zakładam, że klucz obcy nie jest zerowalny i dlatego usunięcie obiektu wymaga usunięcia powiązanego obiektu (usuwanie kaskadowe). Możesz sprawdzić ten wątek: http://stackoverflow.com/questions/10300156/ivalidatableobject-is-useless-for-ef-navigation-properties/10304323#10304323. Może to być pomocne, ponieważ pokazuje, jak dostać się do powiązanych obiektów. – Pawel

+0

To było pomocne w uzyskaniu powiązanych obiektów, dziękuję. Jednak próbując zmienić stan jednej z relacji, pojawia się dziwny błąd, który mówi: "Nie można zmienić stanu związku, jeśli jednym z końców związku jest KeyEntry". – Jonathan

+0

Czy obejrzałeś [to obejście] (http://connect.microsoft.com/VisualStudio/feedback/details/513174/unable-to-refresh-some-items-in-the-objectcontext)? –

Odpowiedz

0

Najpierw należy delikatnie usunąć potomki w relacjach rodzic-dziecko. Zacznij od najwyższego rodzica i powtórz swoją drogę przez dzieci. Zaznacz każdy odwiedzany element, aby można było śledzić, czy został już usunięty w miękki sposób (w przypadku odniesienia do tyłu).

Jeśli masz pojęcie "obiektu biznesowego", możesz dodać właściwości Childs i Parent, aby ułatwić nawigację. W przeciwnym razie będziesz musiał "ręcznie kodować" to na każdym Rodzicu z nietrywialnymi relacjami między dziećmi.

Zauważ również, że za pomocą jednej instrukcji LINQ nie masz kontroli nad rzeczywistym przejazdem.

Wiem, że powyższe wydaje się dużo pracy, ale zastanów się, jak można urządzenie mechanizm w EF, który automatycznie wnioskuje potrzebne informacje o związku ?! Właściwie skończyłbyś robić takie rzeczy.