7

Pracuję nad moją aplikacją ASP.NET MVC już od wielu miesięcy. Kiedy zaczynałem pracę nad tym, używałem Entity Framework 4.3 (Code-First w/Migrations). Kiedy to robiłem, napotkaliśmy pewne problemy podczas próby aktualizacji na mojej tabeli MainClient. MainClient zawiera wszystkie podstawowe informacje klienta i ma relację 1: 1 z tabelą BPClient, która zawiera bardziej szczegółowe informacje o tym kliencie odnoszące się do umowy licencyjnej dla modułu BP. Oba można edytować na tej samej stronie w kontrolce karty. Ja jednak przechowywane na otrzymuję następujący wyjątek podczas próby zmiany EntityState obiektu MainClient do bycia EntityState.Modified:Entity Framework 4.3 vs. 5.0 Aktualizowanie różnic

System.InvalidOperationException : An object with the same key already exists 
in the ObjectStateManager. The ObjectStateManager cannot track multiple objects 
with the same key. 

zauważyłem podczas debugowania, że ​​sam obiekt został uznany wolnostojący, gdy poszedł do mojej klasy Controller być uratowanym. Jako obejście tego problemu zastosowałem podobne rozwiązanie do problemów znalezionych w this blog post i this SO question. Oto jak kod do ponownego mocowania przedmiotów wyglądało potem (brudny, wiem), biorąc pod uwagę sposób Edit były przekazywane w obiekcie MainClient zwanego client:

var newClientObject = new MainClient { ClientID = client.ClientID }; 
Db.MainClients.Attach(newClientObject); 
Db.Entry(newClientObject).CurrentValues.SetValues(client); 

var bpClient = new BPClient { ClientID = client.ClientID, BaseClient = newClientObject }; 
if (client.BPClient != null) 
{ 
    Db.BostonpostClients.Attach(bpClient); 
    Db.Entry(bpClient).CurrentValues.SetValues(client.BPClient); 
} 

Db.SaveChanges() 

To działało tylko cacy przez wszystkich przypadków testowych. Do niedawna.

Niedawno uaktualniłem swoją aplikację, aby używać Entity Framework 5 (nadal przy użyciu Code-First). Kiedy ponownie testowałem stronę edycji MainClient, zauważyłem raczej nieregularne zachowanie. Niektóre pola, po edycji, zostaną zapisane bez problemów. Inni nigdy nie byliby zobowiązani do DB. Jeszcze inni utrzymaliby się dobrze, ale tylko wtedy, gdy byli jedyną częścią edytowanego obiektu. I debugowałem do DbContext, który był w klasie Controller, i znalazłem, dość irytująco, że nie tylko zmiany dokonane na stronie są wysyłane do klasy Controller, ale że ObjectStateManager miał zarówno obiekty MainClient i BPClient w to ze zmianami, które zostały wprowadzone na stronie! Należy wspomnieć tutaj, przy okazji, że nie otrzymałem jednego błędu podczas debugowania go, nawet po SaveChanges().

postanowiłem spróbować przywrócić kod do tego, co było pierwotnie, to znaczy logiczny sposób to zrobić:

Db.Entry<BPClient>(client.BPClient).State = EntityState.Modified; 
Db.Entry<MainClient>(client).State = EntityState.Modified; 

Db.SaveChanges(); 

A teraz to działa całkowicie w porządku. Brak wyjątku InvalidOperationException. Tak więc zostało to rozwiązane.

To, co nadal mnie dręczy, to próbowanie dowiedzieć się, co zmieniło się w wersji 5.0, dzięki czemu moja wcześniejsza poprawka przestała działać i sprawiła, że ​​poczułem się nieswojo. Dlaczego ten kod działa poprawnie w wersji 4.3, ale nie w wersji 5.0? Co w 5.0 spowodowało, że popełnienie błędu w bazie danych było tak błędne?

Czy ktoś wie, dlaczego tak się stało?

+0

To może być pomocne. Entity Framework 5 Enums i Moving Solution z EF 4.3 http://thedatafarm.com/blog/data-access/video-entity-framework-5-enums-and-moving-solution-from--3-4/ – Aru

Odpowiedz

0

Sam miałem ten problem. Używałem klas IDbSet do zapełniania tabel bazy danych, co odkryłem podczas tworzenia właściwości wirtualnej EF5 wykonuje leniwy ładunek (moje właściwości wirtualne, w których znajdują się inne obiekty w bazie danych). Oznacza to, że otrzymuję nowy klucz podstawowy dla wirtualnej nieruchomości. No cóż, jeśli nie mam konkretnego identyfikatora związanego z obiektem, chcę odwołać się do EF 5, próbując stworzyć dwukierunkową relację. Jeśli nie powiesz konkretnie, którą właściwość ma odwzorować w DBContext, ustawia dwa klucze obce dla tego samego obiektu, co nie jest dozwolone. Mam nadzieję że to pomoże.

+0

Dzięki za próbę odpowiedzi na moje pytanie. Nie sądzę, że tak jest w tym przypadku.Ustawiłem już 1: 1 między MainClient i BPClient jako relację dwukierunkową (zarówno z właściwościami wirtualnymi, jak iz identyfikatorami). Próbuję tylko zrozumieć, dlaczego kod nagle przestał działać. – IronMan84

+0

używanie tylko wirusów powoduje leniwy ładowanie, czy ta sama mapa jest wykonana w dbcontext między właściwościami? – Robert

+0

Używam adnotacji danych, a nie interfejsu API FLUENT. Mapowanie odbywa się całkowicie na samym obiekcie, a nie w DbContext. Czy coś się stało między 4.3 a 5.0 w odniesieniu do leniwego ładowania, które wpłynęłoby na kod w taki sposób? – IronMan84

Powiązane problemy