Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'operace Databáze očekává, že ovlivní 1 row(s), ale ve skutečnosti ovlivněn 2. řada(s)

0

Otázka

Dostal jsem tuto chybu jednou jsem se snaží aktualizovat tabulky se stejnou hodnotou (carNumber), můj stav je aktualizovat, kde skutečné datum návratu pole je null.

Z nějakého důvodu, zdá se, že dotaz vrátí 2 řádky, ale ve skutečnosti je tam jen jeden. Používám EF. To je funkce:

chyba - print screen

   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();

Chybové zvýšit, když se snaží db.saveChanges()

tabulku z db, auto, číslo je 1000 - print screen

modelBuilder.Subjekt pic

prosím, dejte mi vědět, jak můžu vyřešit tento problém.

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

problém vyřešen přidat nový sloupec car_rental_fields tabulky, sloupce id, které zahrnují Identity. jak jsem pochopil z tu a z webu, tam je problém s komplikovanými pk. v mém řešení id není primárním klíčem, ale je to logika pro linq aktualizovat správného sloupce. díky za všechny lidi, kteří se v této otázce angažuje.

2021-11-26 20:37:27
0

K této chybě dochází, když EF nemůže vyřešit PK pro váš subjekt. Ve většině případech pro jednoduché bytosti, EF konvence mohou fungovat PK, ale ve vašem případě používáte kompozitní klíč, takže to musí být nakonfigurován. V závislosti na tom, jak jste mapování entity můžete to udělat buď v:

  • o EDMX
  • v DbContext.OnModelCreating
  • pomocí EntityTypeConfiguration prohlášení
  • pomocí atributů v rámci subjektu samotného

Jelikož nevíme, jak vaše bytosti jsou nakonfigurovány, můžete si to ověřit jako příčinu pomocí atributu přístupu ve vašem subjektu jako test. Pokud používáte EDMX tříd entit budou generovány, takže budete chtít nahradit tento s konfiguraci v rámci EDMX. (Nemůžeme vám pomoci, protože nemám používat dang věci :D )

Pravděpodobně budete mít něco jako:

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...
}

Můžete dokonce mít [Key] atribut na jednom z těchto polí, jako CarNumber. Pokud je PK mapována na subjekt, problém je, že to není dostatečně konkrétní k jednoznačné identifikaci řádku. Když EF jde aktualizovat jeden subjekt, je kontrola, a očekával, že aktualizace pouze jeden řádek v tabulce. Je to nalezení více než jeden řádek bude ovlivněna tak to selže.

Přidat atributy pro [Key] s sloupec pořadí, takže to je uznáván jako složený klíč.

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...
}

Za předpokladu, že tyto 4 sloupce jsou zaručeně jedinečné omezení na stůl, EF bude spokojen, když pouze jeden řádek je aktualizován, když se to staví je SQL příkaz UPDATE.

Znovu si všimněte, že pokud to funguje a používáte EDMX, budete muset přezkoumat a upravit svůj EDMX mapování provést příslušné změny od třídy entity by mohly být obnoven, ztrácí své další atributy. (Věřím, že vytvořené entity tříd z EDMX mít komentář záhlaví varování, že se jedná o generované třídy, takže to je indikátor pozor.)

Aktualizace: Můj hlavní podezřelý v tomto by se stát, že tabulka není ve skutečnosti mají odpovídající PK definován, a to buď běží jiný PK kombinace, nebo více pravděpodobné č. PK vzhledem k povaze těchto oblastech. EF mohou být provozovány na tabulky, které nemají žádné PK definovány, ale to vyžaduje Klíčovou definici, která zajišťuje, že záznamy mohou být jednoznačně identifikovány. Chybové vidíte se stane, když ten klíč definice není dost unikátní. (I. e. pokud aktualizujete auto 1, a výběru řádku, který má: car_number = 1, start_day = 2021-11-21, return_day = 2021-11-22, user_id = 0 problém je, že více než jeden řádek se, že kombinace v DB. Pokud DB kontrolujete nemá mít více než jeden odpovídající řádek pak se vaše aplikace je téměř jistě ukazuje na jiné databáze než ty běžný.

Věci, které můžete udělat, chcete-li to ověřit:

  1. ten runtime řetězec připojení a uvidíme, jestli to odpovídá DB kontrola:

Před spuštěním dotazu, přidejte následující:

// EF6
var connectionString = db.Database.Connection.ConnectionString;
// EF Core 5
var connectionString = db.Database.GetConnectionString();
  1. Podívejte se na data, jsou ve skutečnosti dotazování:

.

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

Zatímco tento dotaz může vrátit pouze 1 záznam, že není příčinou problému. To, co chcete, je CarNumber, Počátečnídatum, ReturnDate, a Uživatelské jméno pro tento záznam:

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.

Tyto dotazy vyberte předpokládá, že hodnoty PK pro auto záznam myslíš aktualizovat, pak hledání auta pro odpovídající záznamy s očekávaným Klíčových oblastech. Sázel bych na to, že zatímco horní dotaz vrátí 1 záznam, dolní dotaz vrátí dva řádky, což znamená, zatímco pouze 1 záznam má #null ActualReturnDate hodnota, Klíč není dost unikátní pro obsah této tabulky.

2021-11-26 22:57:48

používám souvislostech, viděl jsi můj otisk obrazovky model builder?
elirans

Ano, dobře, že je pomocí DbContext je OnModelCreating modelBuilder, takže Klíčem je být definovány. Další věc, kterou musíte zkontrolovat, zda bude tyto sloupce odpovídají PK /w jedinečné omezení v příslušné databázi. Ne-li, že klíč může být třeba rozšířit. Kompozitní klíče je třeba se vyhnout, stejně jako je to možné, jak oni dělají nastavení vztahů mnohem více práce. Můžete také použít profiler k zachycení navrhované aktualizace prohlášení, a pak převést do jednoduché VYBRAT, aby viděli, co řádky jsou vráceny. Z nějakého důvodu více než jedné řádky se vracejí.
Steve Py

Další věc ke kontrole je, zda za běhu aplikace je bít stejné databáze, jako to, co jste kontrolu. Data jsou kontrola může zdát natolik unikátní, že pokud DB není prosazování jedinečné omezení na ty sloupy, ale databáze je ukázal v runtime má duplicitní řádky.
Steve Py

stejné chyby se vyskytují použitím vašeho řešení, jsem musel změnit své funkci také? @Steve Py
elirans

Zachytit SQL jsou generovány a spustit na databázi. Já obvykle používají Profiler pro tento, tak pro SQL Server a SSMS, pod Tools\SQL Profiler. Běh, který proti své DB, pak spustit váš dotaz. Můžete použít zarážky v aplikaci těsně před SaveChanges, pak je jasné, výstup profiler před dalším použitím vyčistit předchozí hluku a najít AKTUALIZACI prohlášení.
Steve Py

Také, můžete po stole návrháře výstup pro váš stůl? Má tabulka mít skutečnou PK set s těmi, 4 sloupce?
Steve Py

Přidal jsem na odpověď výše zahrnovat kroky k double-zkontrolujte, zda řetězec připojení, stejně jako ověřit v datech, zda existují duplicitní hodnoty klíče.
Steve Py

Zkoušela jsem vaše řešení. první věc, co vypadá to, že vám chybí některé '=' v autech var. druhá věc - když jsem se snažit, aby aktualizace: auta.ActualReturnDate = acctualDate1; dostal jsem chybové cs1061.
elirans

V jiných jazycích

Tato stránka je v jiných jazycích

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