2011-07-19 8 views
5

Używam EF 4.1 najpierw kod SQL CE 4.0EF 4.1 Kod pierwszego SQL CE 4.0 aktualizacja kolekcja wyjątek

mam dwie klasy

public class Customer 
{ 
    public int ID { get; set; } 

    public string CompanyName { get; set; } 

    public List<ContactPerson> ContactPersons { get; set; } 
} 

public class ContactPerson 
{ 
    public int ID { get; set; } 

    public string Name { get; set; } 

} 

i DbContext

public class MyDB : DbContext 
{ 
    public DbSet<ContactPerson> ContactPersons { get; set; } 

    public DbSet<Customer> Customers { get; set; } 

    public MyDB() 
    { 
     this.Configuration.LazyLoadingEnabled = true; 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Customer>() 
      .HasMany(c => c.ContactPersons) 
      .WithRequired() 
      .WillCascadeOnDelete(true); 
    } 
} 

W tym samym czasie w kodzie muszę zaktualizować całą kolekcję ContactPerson klienta.

List<ContactPersons> modifiedContactPersons; 
Customer customer = MyDB.Customers.Find(ID); 
customer.ContactPersons = modifiedContactPersons; 

gdy zgłoszę MyDB.SaveChanges() pojawia się następujący wyjątek:

Wystąpił błąd podczas zapisywania podmioty, które nie narażają klucz obcy właściwości ich relacji. Właściwość EntityEntries zwróci wartość null , ponieważ nie można zidentyfikować pojedynczej encji jako źródła wyjątku. Obsługa wyjątków podczas zapisywania może być łatwiejsza dzięki ujawnieniu właściwości klucza obcego w typach jednostek. Szczegółowe informacje można znaleźć w artykule InnerException pod adresem .

z InnerException:

Związek z AssociationSet określenia 'Customer_ContactPersons' jest określenia 'usunięty' stanu. Biorąc pod uwagę ograniczenia wielokrotności, odpowiedni " " Customer_ContactPersons_Target "również musi być w stanie" Usunięte ".

Rozumiem, co to oznacza, ale nie mogę rozwiązać problemu sam. Jakieś sugestie?

Odpowiedz

8

Tutaj problemem jest to:

customer.ContactPersons = modifiedContactPersons; 

Zastępuje lista starych powiązanych osób kontaktowych z listą nowych powiązanych osób kontaktowych i robi dwie operacje:

  • To pierwszy znak odniesieniu do wszystkich poprzednio powiązane osoby do Deleted
  • Następnie dołączają wszystkie nowe osoby kontraktowe i znakują z nimi relację jako Added

Pierwsza operacja jest problemem, ponieważ usunięcie relacji nie powoduje usunięcia powiązanego obiektu, więc kończy się ContactPerson, co nie jest związane z żadnymi nie jest dozwolone przez twoje mapowanie (FK nie jest zerowalne).

Rozwiązanie tego problemu zależy od wymagań, które próbujesz osiągnąć. Jeśli naprawdę chcesz usunąć wszystkie powiązane osoby najpierw, musisz ustawić stan każdego z nich, aby został usunięty ręcznie przed przypisaniem nowej listy. Jeśli chcesz zaktualizować istniejące osoby, nie powinieneś tego robić w ogóle. Powinieneś powtórzyć osoby związane z klientem i zmodyfikować swoje dane z nowej listy. Czemu?Ponieważ:

  • Jeśli usuniesz podmiot i włożyć nową zamiast aktualizacji istniejącego będziesz miał dwa oświadczenia modyfikacji bazy danych zamiast jednego = dwa roundtrips do bazy danych zamiast jednego, aw przypadku wielu podmiotów będzie powolny wiele aplikacji
  • Jeśli masz inny podmiot zależny od ContractPerson, nie możesz go usunąć. Również jeśli używasz ContractPerson 's Id gdzieś i jeśli jest on generowany automatycznie, nie będzie już więcej po usunięciu oryginalnego rekordu.
  • Jest to generalnie bardzo złe i leniwe podejście. Wstaw nowe rekordy, zmodyfikuj istniejące rekordy i usuń tylko rekordy, które naprawdę powinny zostać usunięte.
+0

Piszesz: "Powinieneś powtórzyć osoby związane z klientem i zmodyfikować swoje dane z nowej listy". Jak zrobić to w najprostszy sposób? – esba

Powiązane problemy