Microsoft.EntityFrameworkCore.Wyjątek DbUpdateConcurrencyException: "Oczekuje się, że operacja się z bazą danych wpłynie na 1 wiersz(wiersze), ale faktycznie wpłynęła na 2 wiersze(wiersze)

0

Pytanie

Mam ten błąd, jak tylko próbuję zaktualizować tabelę o tej samej wartości (liczba porządkowa), mój warunek-zaktualizować, jeśli pole rzeczywistej daty zwrotu jest równa zero.

Z jakiegoś powodu to wygląda tak, jakby kwerenda zwraca 2 wiersze, ale w rzeczywistości jest tylko jedna. Używam EF. To jest funkcja:

ekran z błędem - drukowanie

   public void updateStatus(int carNumber1, string acctualDate1)
    {
        DateTime accReturn = DateTime.Parse(acctualDate1);

        var orderCar1 =  db.CarRentalFields.FirstOrDefault(carNum =>
        (carNum.CarNumber == carNumber1 && carNum.ActualReturnDate == null));

            orderCar1.ActualReturnDate = accReturn  ;
             
                db.SaveChanges();

Błąd występuje podczas próby db.SaveChanges()

tabela z bazy danych, pokój samochodu 1000 - wydruk ekranu

Konstruktor modeli.Obraz obiektu

proszę, daj mi znać, jak mogę rozwiązać ten problem.

c# entity-framework linq sql-server
2021-11-23 20:34:34
2
0

problem został rozwiązany przez dodanie nowej kolumny do tabeli car_rental_fields, kolumny identyfikatora zawierającego identyfikator. jak rozumiem stąd i z Internetu, istnieje problem ze złożonym pc. w moim rozwiązaniu identyfikator nie jest kluczem podstawowym, ale to sprawia, że logikę linq do aktualizacji właściwej kolumny. dziękuję wszystkim ludziom, którzy uczestniczyli w tej sprawie.

2021-11-26 20:37:27
0

Ten błąd występuje, gdy EF nie może zezwolić na PK dla swojej istocie. W większości przypadków dla prostych bytów umowy EF mogą ustalać PK, ale w twoim przypadku używasz klucz złożony, dlatego należy go skonfigurować. W zależności od tego, jak zbieracie swoje istocie, można to zrobić w:

  • EDMX
  • w DbContext.Tworzenie modelu
  • za pomocą EntityTypeConfiguration deklaracja
  • korzystanie z atrybutów wewnątrz samej encji

Ponieważ nie wiemy, jak dostosować swoje encji, możesz to sprawdzić, jak powód, wykorzystując podejście atrybutów w swojej istocie jako test. Jeśli używasz EDMX, klasy encji będą generowane, więc chcesz wymienić to konfiguracją w EDMX. (Nie mogę ci w tym pomóc, bo nie używam te cholerne rzeczy :D )

U ciebie pewnie będzie coś takiego:

public class CarRentalFields
{
    [Column("start_day")]
    public DateTime StartDay { get; set; }
    [Column("return_date")]
    public DateTime ReturnDate { get; set; }
    [Column("user_id")]
    public int UserId { get; set; }
    [Column("car_number")]
    public DateTime CarNumber { get; set; }
    
    // ... more columns...
}

Być może masz nawet [Key] atrybut w jednym z tych pól, na przykład, numer porządkowy. Jeśli w istocie jest wyświetlany PK, problem polega na tym, że nie był dość specyficzny, aby jednoznacznie zidentyfikować wiersz. Kiedy EF przechodzi do aktualizacji jednej istocie, on sprawdza i czeka na aktualizacje tylko jednego wiersza w tabeli. To doprowadzi do tego, że będzie narażona na więcej niż jeden wiersz, więc to nie uda.

Dodaj atrybuty [Key] kolejność kolumn, aby został rozpoznany jako klucz złożony.

public class CarRentalFields
{
    [Key, Column(Name="start_day", Order=1)]
    public DateTime StartDay { get; set; }
    [Key, Column(Name="return_date", Order=2)]
    public DateTime ReturnDate { get; set; }
    [Key, Column(Name="user_id", Order=3)]
    public int UserId { get; set; }
    [Key, Column(Name="car_number", Order=4)]
    public DateTime CarNumber { get; set; }
    
    // ... more columns...
}

Pod warunkiem, że te 4 kolumny gwarantowane są wyjątkowym ograniczeniem dla tabeli, EF będzie zadowolony, jeśli podczas tworzenia instrukcji języka SQL UPDATE będzie przeglad zrobiono tylko jeden wiersz.

Jeszcze raz należy zwrócić uwagę, że jeśli to działa i używasz EDMX, trzeba będzie zobaczyć i zmienić wyświetlanie EDMX, aby wprowadzić odpowiednie zmiany, ponieważ ta klasa encji może być przywrócony, tracąc swoje dodatkowe atrybuty. (Zakładam, że wygenerowane klasy encji z EDMX mają tytuł komentarza, ostrzeżenia o tym, że to wygenerowane klasy, więc jest to wskaźnik, na który należy zwrócić uwagę.)

Odśwież: Moje główne podejrzenie w tym będzie polegała na tym, że w tabeli w rzeczywistości nie jest zdefiniowany odpowiedni PK, albo jest używana inna kombinacja PK, albo, co bardziej prawdopodobne, nie ma PK, biorąc pod uwagę naturę tych pól. EF może pracować z tabelami, dla których nie określono PK, ale do tego potrzebne jest określenie klucza, zapewniające unikalną identyfikację rekordów. Błąd, który widzisz, występuje, gdy jest to definicja klucza za mało jest unikalna. (tzn. Jeśli aktualizujesz car 1 i wybierz linię, która ma: car_number = 1, start_day = 2021-11-21, return_day = 2021-11-22, identyfikator użytkownika = 0 Problem w tym, że w bazie danych więcej niż jeden wiersz zawiera taką kombinację. Jeśli w bazie danych, którą wybrałeś, nie więcej niż jeden zbiega się wiersza, to twoja aplikacja prawie na pewno wskazuje na innej bazy danych niż sprawdzasz.

Co można zrobić, aby upewnić się w tym:

  1. uzyskaj ciąg połączenia w czasie wykonywania i zobacz, czy odpowiada ona bazie danych, którą sprawdzasz:

Przed wykonaniem kwerendy dodaj następujący:

// EF6
var connectionString = db.Database.Connection.ConnectionString;
// EF Core 5
var connectionString = db.Database.GetConnectionString();
  1. Spójrz na dane, które faktycznie wniosek:

.

var cars =  db.CarRentalFields.Where(carNum =>
    (carNum.CarNumber == carNumber1 && carNum.ActualReturnDate == null)).ToList();

Chociaż to zapytanie może zwrócić tylko 1 wpis, to nie jest przyczyną problemu. Czego potrzebujesz, to numer, data rozpoczęcia, data zwrotu i identyfikator użytkownika dla tego konta:

var car =  db.CarRentalFields
    .Where(carNum => carNum.CarNumber == carNumber1 
        && carNum.ActualReturnDate == null)
    .Select(x => new 
    {
        x.CarNumber,
        x.StartDay,
        x.ReturnDate,
        x.UserId
    }).Single(); // Expect our 1 record here...
var cars = db.CarRentalFields
    .Where(x => x.CarNumber == car.CarNumber
        && x.StartDay == car.StartDay
        && x.ReturnDate == car.ReturnDate
        && x.UserId == car.UserId)
    .ToList(); // Get rows that match our returned Key fields.

Te żądania wybierają rzekome wartości PK dla nagrywania samochodu, który chcesz zaktualizować, a następnie wykonują wyszukiwanie samochodów do mapowania kont z oczekiwanymi kluczowymi polami. Ja bym postawił na to, że choć górny zapytanie zwraca 1 wpis, dolny zapytanie zwraca dwa wiersze, to jest, choć tylko 1 wpis ma wartość #null ActualReturnDate, twój klucz nie wystarczy wyjątkowy dla zawartości tej tabeli.

2021-11-26 22:57:48

używam contex, widziałeś mój ekran drukowania konstruktora modeli?
elirans

Tak, dobrze, że jest używany moduł budowania modeli OnModelCreating DbContext, więc kluczem jest określona. Następną rzeczą, którą trzeba sprawdzić, czy spełniają te kolumny ograniczenia unikalności PK /w w twoim odpowiedniej bazie danych. Jeśli nie, to ten klucz, być może trzeba będzie poszerzyć. Kluczy złożonych należy unikać, o ile jest to możliwe, ponieważ są one znacznie utrudniają ustawienie relacji. Można również korzystać z profiler do przechwytywania proponowanego operatora aktualizacji, a następnie przekształcić go w prosty WYBÓR, aby zobaczyć, jakie polecenia są zwracane. Z jakiegoś powodu wraca kilka wierszy.
Steve Py

Jeszcze jedna rzecz, którą należy sprawdzić, to trafia czy aplikacja w czasie wykonywania tej samej bazy danych, co i sprawdzasz. Dane, które sprawdzasz, mogą wydawać się dość wyjątkowe, jeśli baza danych nie stosuje ograniczenie unikatowości do tych kolumn, ale baza danych, na którą wskazują, że w czasie wykonywania, zawiera zduplikowane wiersze.
Steve Py

ten sam błąd występuje podczas korzystania z danego rozwiązania, czy trzeba było również zmienić moją funkcję? @Steve Pai
elirans

Weź wygenerowany SQL i uruchom go w bazie danych. Zazwyczaj używam do tego profiler, więc dla programu SQL Server i SSMS w dziale Narzędzia\SQL Profiler. Uruchom to w swojej bazie danych, a następnie wykonaj zapytanie. Można użyć pułapki w swojej aplikacji bezpośrednio przed zapisaniem zmian, a następnie wyczyść dane wyjściowe programu profiler przed wznowieniem, aby usunąć poprzedni hałas i znaleźć instrukcję UPDATE.
Steve Py

Ponadto, czy można publikować dane wyjściowe projektu tabeli do tabeli? Czy w tabeli rzeczywisty zestaw PK z tych 4 kolumn?
Steve Py

Dodałem do odpowiedzi powyżej, aby włączyć kroki do podwójnej kontroli parametrów połączenia, a także sprawdzania, czy w danych powtarzających się wartości kluczy.
Steve Py

Próbowałem twoja decyzja. pierwsze, co wygląda tak, jakby brakowało jakiegoś " = " w samochodach. po drugie - gdy próbuję zrobić aktualizację: samochody.ActualReturnDate = acctualDate1; mam błąd cs1061.
elirans

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................