Korzystam z Entity Framework do wypełnienia kontrolki siatki. Czasami po dokonaniu aktualizacji pojawia się następujący błąd:
Przechowywanie instrukcji aktualizacji, wstawiania lub usuwania wpłynęło na nieoczekiwaną liczbę wierszy (0). Elementy mogły zostać zmodyfikowane lub usunięte od czasu załadowania elementów. Odśwież wpisy ObjectStateManager.
Nie mogę wymyślić, jak to odtworzyć. Ale może to mieć coś wspólnego z tym, jak blisko siebie dokonuję aktualizacji. Czy ktoś to widział lub czy ktoś wie, do czego odnosi się komunikat o błędzie?
Edycja: Niestety nie mam już możliwości odtworzenia problemu, który tu miałem, ponieważ zrezygnowałem z tego projektu i nie pamiętam, czy w końcu znalazłem rozwiązanie, czy inny programista go naprawił, czy też obejrzałem go. Dlatego nie mogę przyjąć żadnych odpowiedzi.
źródło
Request.Uri
aby zobaczyć rzeczywisty adres URL żądania. W moim przypadku miałem trochę logiki śledzenia, która uderzała w moją stronę i niepotrzebnie ładowała kontekst z bazy danych (i od czasu do czasu ją aktualizowałem). Więc wtedy na rzeczywistej stronie, którą debugowałem, dane zostały zdeptane przez głupią logikę kodu śledzenia.Odpowiedzi:
Jest to efekt uboczny funkcji zwanej optymistyczną współbieżnością.
Nie jestem w 100% pewien, jak to włączyć / wyłączyć w Entity Framework, ale w gruncie rzeczy mówi to, że między momentem wyjęcia danych z bazy danych a zapisaniem zmian ktoś inny zmienił dane (co znaczyło, gdy odszedłeś aby go zapisać 0 wierszy zostało zaktualizowanych). W kategoriach SQL klauzula
update
zapytaniawhere
zawiera oryginalną wartość każdego pola w wierszu, a jeśli wpłynie na 0 wierszy, wie, że coś poszło nie tak.Chodzi o to, że nie zastąpisz zmiany, o której nie wiedziała Twoja aplikacja - jest to po prostu mały środek bezpieczeństwa wprowadzony przez .NET we wszystkich twoich aktualizacjach.
Jeśli jest spójny, istnieje prawdopodobieństwo, że dzieje się to zgodnie z twoją logiką (np. Sam aktualizujesz dane inną metodą pomiędzy wyborem a aktualizacją), ale może to być po prostu warunek wyścigu między dwiema aplikacjami.
źródło
Natknąłem się na to i było to spowodowane tym, że pole identyfikatora (klucza) bytu nie było ustawione. Dlatego gdy kontekst poszedł do zapisania danych, nie mógł znaleźć identyfikatora = 0. Pamiętaj, aby umieścić punkt przerwania w instrukcji aktualizacji i sprawdź, czy identyfikator jednostki został ustawiony.
Z komentarza Paula Bellory
źródło
Wow, wiele odpowiedzi, ale dostałem ten błąd, kiedy zrobiłem coś nieco innego, o czym nikt inny nie wspomniał.
Krótko mówiąc, jeśli utworzysz nowy obiekt i powiesz EF, że został zmodyfikowany za pomocą,
EntityState.Modified
to wyrzuci ten błąd, ponieważ nie istnieje jeszcze w bazie danych. Oto mój kod:Tak, to wydaje się głupie, ale pojawiło się, ponieważ omawiana metoda wcześniej
foo
do niego została stworzona wcześniej, teraz tylkosomeValue
przeszła i stworzyłafoo
się.Łatwo naprawić, tylko zmiana
EntityState.Modified
naEntityState.Added
lub zmiana że cała linia do:źródło
Napotkałem ten sam błąd straszenia ... :) Wtedy zdałem sobie sprawę, że zapomniałem ustawić
@Html.HiddenFor(model => model.UserProfile.UserId)
dla klucza podstawowego aktualizowanego obiektu! Często zapominam o tej prostej, ale bardzo ważnej rzeczy!
Nawiasem mówiąc:
HiddenFor
jest dla ASP.NET MVC.źródło
UserId
formularza, bardzo podatnego na ataki hakerów ... po tym należy wypełnićHttpContext.Current.User.Identity.Name
HiddenFor
tak będziesz musiał go pobraćHttpContext
... W ogóle nie umieściłbym tej właściwości w formie, co zmusiłoby mnie do zawsze wypełniania jej po stronie serwera ...Sprawdź, czy zapomniałeś atrybutu „DataKeyNames” w GridView. jest to konieczne podczas modyfikowania danych w GridView
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.datakeynames.aspx
źródło
Problem jest spowodowany jedną z dwóch rzeczy: -
Concurrency Mode: Fixed
.., a optymistyczna współbieżność uniemożliwiła zapisanie danych. To znaczy. niektóre zmieniły dane wiersza między czasem otrzymania danych serwera a momentem zapisania danych serwera.StoreGeneratedPattern = Computed
) I ten wiersz nie istnieje.źródło
Wystąpił ten sam błąd, ponieważ część PK była kolumną daty i godziny, a wstawiany rekord używał DateTime.Now jako wartości dla tej kolumny. Struktura encji wstawiałaby wartość z dokładnością do milisekund, a następnie szukała wartości, którą właśnie wstawiła, również z dokładnością do milisekund. Jednak SqlServer zaokrąglił tę wartość do drugiej precyzji, a zatem środowisko encji nie było w stanie znaleźć wartości precyzji milisekundowej.
Rozwiązaniem było obcięcie milisekund z DateTime.Now przed wstawieniem.
źródło
Date
DateTime
Miałem ten sam problem i @ webtrifusion za odpowiedź pomogła znaleźć rozwiązanie.
Mój model używał
Bind(Exclude)
atrybutu na identyfikatorze jednostki, co powodowało, że wartość identyfikatora jednostki była zerowa na HttpPost.źródło
Miałem ten sam problem, zorientowałem się, że był spowodowany RowVersion, który był zerowy. Sprawdź, czy identyfikator i RowVersion nie mają wartości zerowej .
Aby uzyskać więcej informacji, zapoznaj się z tym samouczkiem
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application
źródło
Zacząłem otrzymywać ten błąd po zmianie z pierwszego modelu na pierwszy. Mam wiele wątków aktualizujących bazę danych, z których niektóre mogą aktualizować ten sam wiersz. Nie wiem, dlaczego nie miałem problemu z pierwszym użyciem modelu, zakładam, że używa innej domyślnej współbieżności.
Aby obsłużyć go w jednym miejscu, znając warunki, w których może wystąpić, dodałem następujące przeciążenie do mojej klasy DbContext:
Następnie nazywane,
SaveChanges(true)
gdziekolwiek dotyczy.źródło
Musisz jawnie dołączyć BoundField klucza podstawowego. Jeśli nie chcesz, aby użytkownik widział klucz podstawowy, musisz go ukryć za pomocą css:
Gdzie „ukryty” to klasa w css, która ma ustawioną opcję wyświetlania na „none”.
źródło
Podczas edycji dołącz identyfikator lub klucz podstawowy encji jako ukryte pole w widoku
to znaczy
to rozwiązuje problem.
Również jeśli twój model zawiera nieużywany przedmiot, to również to i wyślij to do kontrolera
źródło
Natknąłem się również na ten błąd. Okazało się, że problem został spowodowany przez wyzwalacz na stole, na który próbowałem zapisać. Trigger użył „ZAMIAST WSTAWIENIA”, co oznacza, że do tej tabeli kiedykolwiek wstawiono 0 wierszy, stąd błąd. Na szczęście może się zdarzyć, że funkcja wyzwalacza była niepoprawna, ale myślę, że może to być poprawna operacja, którą należy jakoś obsłużyć w kodzie. Mam nadzieję, że to komuś pomoże.
źródło
SELECT SCOPE_IDENTITY() as MyViewId
Natrafiłem na ten problem w tabeli, w której brakowało klucza podstawowego i miał kolumnę DATETIME (2, 3) (więc „klucz podstawowy” encji był kombinacją wszystkich kolumn) ... Podczas wykonywania wstawiania znacznik czasu miał bardziej precyzyjny czas (2018-03-20 08: 29: 51.8319154), który został skrócony do (2018-03-20 08: 29: 51.832), więc wyszukiwanie kluczowych pól nie powiedzie się.
źródło
Też miałem ten błąd. Istnieją sytuacje, w których jednostka może nie być świadoma faktycznego kontekstu bazy danych, którego używasz, lub model może być inny. W tym celu ustaw: EntityState.Modified; do EntityState.Added;
Aby to zrobić:
Zapewni to, że jednostka wie, że używasz lub dodajesz stan, z którym pracujesz. W tym momencie należy ustawić wszystkie prawidłowe wartości modelu. Uważaj, aby nie stracić żadnych zmian, które mogły zostać wprowadzone w tle.
Mam nadzieję że to pomoże.
źródło
Moja wersja wiersza była zerowa, więc musiałem dodać to do widoku, który rozwiązał mój problem
źródło
Linia
[DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]
zrobiła lewę w moim przypadku:źródło
Upewnij się tylko, że tabela i formularz mają zaktualizowany klucz podstawowy i edmx.
odkryłem, że wszelkie błędy podczas aktualizacji były zwykle spowodowane: - Brak klucza podstawowego w tabeli - Brak klucza podstawowego w widoku / formularzu edycji (np.
@Html.HiddenFor(m=>m.Id
)źródło
Miałem ten sam problem. W moim przypadku próbowałem zaktualizować klucz podstawowy, co jest niedozwolone.
źródło
Ten błąd pojawia się sporadycznie podczas korzystania z
async
metody. Nie stało się tak odkąd przełączyłem się na metodę synchroniczną.Błędy sporadycznie:
Działa cały czas:
źródło
Wystąpił ten błąd, gdy usuwałem niektóre wiersze w bazie danych (w pętli) i dodawałem nowe w tej samej tabeli.
Rozwiązaniem było dla mnie dynamiczne tworzenie nowego kontekstu w każdej iteracji pętli
źródło
źródło
Dzieje się tak również wtedy, gdy próbujesz wprowadzić unikalną sytuację z ograniczeniami, tj. Jeśli możesz mieć tylko jeden typ adresu na pracodawcę i próbujesz wstawić drugą tego samego typu u tego samego pracodawcy, otrzymasz ten sam problem .
LUB
Może się to również zdarzyć, jeśli wszystkie właściwości obiektu, do których zostały przypisane, zostały przypisane z takimi samymi wartościami, jak wcześniej.
źródło
Jeśli próbujesz utworzyć mapowanie w pliku edmx na „funkcję Imports”, może to spowodować ten błąd. Po prostu wyczyść pola wstawiania, aktualizacji i usuwania, które znajdują się w Szczegółach mapowania dla danej encji w edmx, i powinno działać. Mam nadzieję, że to wyjaśniłem.
źródło
Ten wyjątek wystąpił podczas dołączania obiektu, który nie istniał w bazie danych. Zakładałem, że obiekt został załadowany z osobnego kontekstu, ale jeśli użytkownik odwiedził witrynę po raz pierwszy, obiekt został stworzony od podstaw. Mamy automatycznie zwiększające się klucze podstawowe, więc mógłbym je wymienić
z
źródło
Mam ten sam problem. Ale było to spowodowane moim błędem. Właściwie zapisywałem obiekt zamiast go dodawać. To był konflikt.
źródło
Jednym ze sposobów debugowania tego problemu w środowisku Sql Server jest użycie Sql Profiler dołączonego do twojej kopii SqlServer, lub jeśli używasz wersji Express, pobierz kopię Express Profiler za darmo z CodePlex, klikając poniższy link:
Express Profiler
Za pomocą Sql Profiler możesz uzyskać dostęp do wszystkiego, co jest wysyłane przez EF do bazy danych. W moim przypadku było to:
Skopiowałem wkleiłem to do okna zapytania w Sql Server i wykonałem. Rzeczywiście, chociaż uruchomiono, to zapytanie wpłynęło na 0 rekordów, dlatego błąd został zwrócony przez EF.
W moim przypadku problem został spowodowany przez CategoryID.
Identyfikator EF nie został zidentyfikowany przez identyfikator EF wysłany do bazy danych, dlatego dotyczy 0 rekordów.
Nie była to jednak wina EF, ale raczej buggy null łączący „??” instrukcja w widoku kontrolera, który wysyłał bzdury do warstwy danych.
źródło
Żadna z powyższych odpowiedzi nie obejmowała mojej sytuacji ani jej rozwiązania.
Kod, w którym błąd został zgłoszony w kontrolerze MVC5:
Otrzymałem ten wyjątek, gdy zapisywałem obiekt poza widokiem edycji. Powodem tego było to, że kiedy wróciłem, aby go zapisać, zmodyfikowałem właściwości, które utworzyły klucz główny na obiekcie. Zatem ustawienie jego stanu na Zmodyfikowany nie miało sensu dla EF - był to nowy wpis, a nie zapisany wcześniej.
Możesz rozwiązać ten problem, albo A) modyfikując wywołanie zapisu, aby dodać obiekt, lub B) po prostu nie zmieniaj klucza podstawowego podczas edycji. Zrobiłem B).
źródło
Kiedy zaakceptowana odpowiedź brzmiała: „ nie spowoduje to zastąpienia zmiany, o której nie wiedziała Twoja aplikacja ”, byłem sceptyczny, ponieważ mój obiekt został nowo utworzony. Ale potem okazuje się, że było
INSTEAD OF UPDATE, INSERT- TRIGGER
do tabeli dołączono załącznik, który aktualizował kolumnę obliczeniową tej samej tabeli.Gdy zmienię to na
AFTER INSERT, UPDATE
, działało dobrze.źródło
Zdarzyło mi się to z powodu niedopasowania między datetime a datetime2. O dziwo zadziałało dobrze, zanim tester odkrył problem. Model My Code First obejmował DateTime jako część klucza podstawowego:
Wygenerowana kolumna jest kolumną daty i godziny. Podczas wywoływania SaveChanges EF wygenerował następujący kod SQL:
Ponieważ próbował dopasować kolumnę datetime do wartości datetime2, nie zwrócił żadnych wyników. Jedyne rozwiązanie, o jakim mogłem pomyśleć, to zmienić kolumnę na datetime2:
źródło
datetime
kontradatetime2
. Zasadniczo niektóre wartości milisekund będą pasować do siebie, inne nie. To samo przydarzyło mi się i również się zmieniłemDateTime2
.