2013-04-08 12 views
11

Otrzymuję następujący błąd z mojego kontekstu DbContext: "Naruszone zostało przekroczenie wielu powiązań. Rola" Moja własność "relacji" MyModel.FK_ChildEntities_MyEntities "ma wielokrotność 1 lub 0..1."Naruszone wiązanie wielokrotności. Rola "..." relacji "..." ma krotność 1 lub 0..1

użyciu ASP.NET, Entity Framework 4

Praca z jednorodzinnego podmiotu

błąd pojawia się drugi raz spróbować ponownie podłączyć jednostkę do dbcontext. Scenariusz jest nieudanym zapisem, po którym następuje ponowna próba.

Mam odłączony podmiot w sesji. Użytkownik zmienia właściwości w formularzu, dodaje rzeczy, usuwa rzeczy i ostatecznie zapisuje kliknięcia. Dostaję załączoną kopię obiektu z nowej instancji dbcontext, stosuję zmiany z odłączonej jednostki do dołączonej jednostki, sprawdzam poprawność, znajduję błąd i przerywam. Użytkownik zmienia cokolwiek i zapisuje ponownie.

Przy drugim zapisie cały proces zapisu powtarza się, tylko tym razem wszystko idzie do piekła. Prawie wszystko jest powielane, powodując jeden błąd lub inny lub wszystkie z nich. Wartości z widoków i tabel wyszukiwania, które mają być tylko referencjami, są tworzone jako nowe i przypisane identyfikatory. Większość z tych problemów udało mi się rozwiązać, ale mam problem z błędem liczności. Elementy potomne są tworzone jako dokładne kopie innych elementów potomnych, aż do unikalnego identyfikatora, tylko w stanie Dodany. Lub, jeśli odwołuję się do pewnych właściwości, zamiast klonowania niezmodyfikowanego potomka, upuszcza nowe. Tak czy inaczej, żaden z kodów nie jest wykonywany tak, jak za pierwszym razem.

Odrzucam instancję dbcontext i załączonego obiektu, każdą próbę zapisu. Sądziłem, że to wystarczy, aby odwrócić wszelkie zmiany, ale coś musi się trzymać. Jedyną rzeczą, której nie zignorowano ani nie zresetowano, jest odłączony podmiot, który jest w sesji, ale nie wprowadzam w nim żadnych zmian. Przynajmniej nie bezpośrednio.

kod (bardzo uproszczony) jest mniej więcej tak:

void Save() 
{ 
using (var context = new MyContext()) 
{ 
    // detached entity from session 
    MyEntity detachedEntity = (MyEntity)Session["DetachedEntity"]; 

    // attached entity from context 
    MyEntity attachedEntity = context.MyEntities.Single(x=>x.id == detachedEntity.id);  


    // <remove children representing lookup table elements from detachedEntity to prevent duplicates> 
    // <remove children representing view elements from detachedEntity to prevent duplicates> 


    // <apply changes from detachedEntity to attachedEntity> 


    // <add new children> 
    // <remove deleted children> 
    // <update modified children> 


    // <set entity state to unchanged on view and lookup elements of attachedEntity to ensure no duplicates...> 


    // <validate> 


    if (errors.count>0) 
    // <report errors> 
    else 
    context.SaveChanges(); 
} 
} 

jako przykładu, to generuje wielość błąd:

// represents first save: 
    using (var context = new MyContext()) 
    { 
     // detached entity from session 
     MyEntity detachedEntity = (MyEntity)Session["DetachedEntity"]; 

     // attached entity from context 
     MyEntity attachedEntity = context.MyEntities.Single(x=>x.id == detachedEntity.id);  

     int debug1 = context.ChangeTracker.Entries<ChildEntity>().Count(); // debug1 == 0; 

     attachedEntity.ChildEntities.Add(detachedEntity.ChildEntities.First()); 

     int debug2 = context.ChangeTracker.Entries<ChildEntity>().Count(); // debug2 == 1; 

    } 

// represents second save: 
    using (var context = new MyContext()) 
    { 
     // detached entity from session 
     MyEntity detachedEntity = (MyEntity)Session["DetachedEntity"]; 

     // attached entity from context 
     MyEntity attachedEntity = context.MyEntities.Single(x=>x.id == detachedEntity.id);  

     int debug1 = context.ChangeTracker.Entries<ChildEntity>().Count(); // debug1 == 0; 

     attachedEntity.ChildEntities.Add(detachedEntity.ChildEntities.First()); 

     int debug2 = context.ChangeTracker.Entries<ChildEntity>().Count(); // multiplicity error; 

    } 

Odpowiedz

14

jakoś dbcontext pamięta jakie obiekty zostały do ​​niego dodane. jeśli dokładna sam obiekt pojawia się dwukrotnie, to ... wieje

zamiast dodawania jednostek podrzędnych z moim jednorodzinnym podmiotu do załączonej jednej, powinnam już tworzenia nowych kopii każdego dziecka

ChildEntity detachedChild = detachedEntity.ChildEntities.First(); 
attachedEntity.ChildEntities.Add(new ChildEntity { 
    propertyA = detachedChild.propertyA, 
    propertyB = detachedChild.propertyB 
}); 

zamiast

attachedEntity.ChildEntities.Add(detachedEntity.ChildEntities.First()); 
+0

, więc utworzy nową "ChildEntity" i doda ją do "Tabeli ChildEntities", a następnie utworzy związek – Mohsen

+0

Stało się to, gdy moja "załączonaIntencja" ("MojaKoniec") miała kolekcję 'ChildEntity', ale moja' Model ChildEntity "nie miał kolekcji" MyEntity ". Ale chciałem zachować tylko jedną instancję 'ChildEntity', więc kiedy dodałem kolekcję' MyEntity' do 'ChildEntity', mógłbym użyć' attachedEntity.ChildEntities.Add (detachedEntity.ChildEntities.First()); ' – Reuben

+0

@Reuben: Problem z tą ostatnią linią polega na tym, że jeśli masz włączone leniwy ładowanie, załaduje on wszystkie ChildEntities dla tej attachEntity. Zdecydowanie niezbyt wydajna. –

5

Problem polega na tym, że w polu detachedChild.parent powinna być przypisana funkcja attachmentParent.

foreach(var detachedEntity in detachedEntities) 
{ 
    attachedEntity.ChildEntities.Add(detachedEntity); 
    detachedEntity.ParentEntity = attachedEntity; 
} 
+1

THIS. Można by pomyśleć, że dołączenie dziecka do nowego rodzica sprawi, że będzie oczywiste, kto jest prawdziwym rodzicem, ale NIE. Dzięki, to jest rozwiązanie. –

1

Należy sprawdzić właściwości obiektu, który próbujesz dodać. W moim przypadku błędnie odwoływało się do tego samego nieważnego obiektu przy każdym dodawaniu, który mu się nie podobał, a więc rzucił ten sam błąd, który tutaj masz.

0

EF 6 Update

Dla mnie ustawienie stanu obiektu, aby dodał pracował brzmi logicznie również

ChildEntity detachedChild = detachedEntity.ChildEntities.First(); 
var newChild = new ChildEntity { 
    propertyA = detachedChild.propertyA, 
    propertyB = detachedChild.propertyB 
}); 

// Mark all added entity entity state to Added 
attachedEntity.ChildEntities.Add(newChild); 
         db.Entry(newChild).State = EntityState.Added; 

http://www.entityframeworktutorial.net/EntityFramework4.3/update-one-to-many-entity-using-dbcontext.aspx

0

Doświadczyłem tego błędu, kiedy miał właściwości nawigacyjnych, które miały nie ustawiono lub właściwości nawigacji, które należały do ​​niewłaściwego kodu Pierwszy DBContext

Powiązane problemy