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?
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