Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'operazione di Database dovrebbe incidere in 1 fila(s), ma in realtà interessati 2 fila(s)

0

Domanda

Ho ricevuto questo errore una volta che cerco di aggiornare la tabella con lo stesso valore (carNumber), la mia condizione è un aggiornamento in cui l'effettiva data per il ritorno in campo è null.

Per qualche motivo si ha l'impressione che la query restituisce 2 righe, ma in realtà c'è solo uno. Sto usando EF. Questa è la funzione:

l'errore - stampa dello schermo

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

L'errore di alzare quando si cerca di db.saveChanges()

la tabella dal db, il numero di targa è di 1000 - stampa dello schermo

modelBuilder.Entità pic

per favore fatemi sapere come posso risolvere questo problema.

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

problema risolto da aggiungere una nuova colonna a car_rental_fields tabella, colonna di id di Identità. a quanto ho capito da qui e dal web, c'è un problema complicato pk. nella mia soluzione l'id non è una chiave primaria, ma è rendere la logica per linq per aggiornare la colonna corretta. grazie per tutte le persone che sono coinvolti in questo problema.

2021-11-26 20:37:27
0

Questo errore si verifica quando EF non è possibile risolvere il PK per la propria entità. Nella maggior parte dei casi per una semplice entità, EF convenzioni possono lavorare fuori il PK, ma nel tuo caso si utilizza una chiave composta quindi questo deve essere configurato. A seconda di come si mappatura delle entità che si può fare questo in:

  • un EDMX
  • in DbContext.OnModelCreating
  • utilizzando un EntityTypeConfiguration dichiarazione
  • l'utilizzo di attributi all'interno dell'ente stesso

Dal momento che non sappiamo come entità sono configurati, si può verificare come la causa utilizzando l'attributo approccio all'interno della vostra entità come un test. Se si utilizza un EDMX le classi di entità verrà generato in modo che si vuole sostituire con configurazione EDMX. (Non si può davvero aiutarti perché non uso il dang cose :D )

Probabilmente qualcosa di simile a:

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

Si può anche avere un [Key] attributo su uno di questi campi, come CarNumber. Se c'è un PK mappati nell'entità il problema è che non è abbastanza specifico per identificare univocamente la riga. Quando EF va ad aggiornare entità, è il controllo di, e in attesa di aggiornare solo una riga nella tabella. Si tratta di trovare più di una riga sarà influenzato in modo non riesce.

Aggiungere gli attributi per il [Key] con l'ordine delle colonne in modo che è riconosciuta come una chiave composta.

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

Fornite queste 4 colonne sono garantiti per essere un vincolo univoco sul tavolo, EF sarà soddisfatto solo quando una riga viene aggiornata quando si costruisce l'istruzione SQL UPDATE.

Notare ancora una volta che se questo funziona e si utilizza un EDMX, sarà necessario rivedere e modificare il vostro EDMX mappatura di apportare le opportune modifiche dal momento che la classe di entità potrebbero essere rigenerati, di perdere i vostri attributi extra. (Credo generato classi di entità da un EDMX avere un commento di intestazione avvertenza che si tratta di una classe generata, in modo che è un indicatore di guardare fuori per.)

Aggiornamento: Il mio primo sospetto in questo sarebbe che il tavolo, in realtà, non hanno un corrispondente PK definito, in un diverso PK combinazione, o più probabilmente no PK, data la natura di tali campi. EF può operato tabelle che non PK definito, ma richiede una Chiave di definizione che garantisce registrazioni possono essere identificati in modo univoco. L'errore che si sta vedendo succede quando la chiave definizione non è abbastanza unico. (I. e. se si sta aggiornando auto 1, e la selezione di una riga: car_number = 1, start_day = 2021-11-21, return_day = 2021-11-22, user_id = 0 Il problema è che più di una riga è questa combinazione nel DB. Se il DB si sta verificando che non hanno più una sola riga corrispondente, l'applicazione è quasi certamente punta a un database diverso da quello che si sta verificando.

Cose che si possono fare per verificare questa:

  1. ottenere il runtime stringa di connessione e vedere se corrisponde il DB che si sta verificando:

Prima di eseguire la query, aggiungere il seguente:

// EF6
var connectionString = db.Database.Connection.ConnectionString;
// EF Core 5
var connectionString = db.Database.GetConnectionString();
  1. Guarda i dati che si sta effettivamente eseguendo la query:

.

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

Mentre questa query restituisce solo 1 record, che non è la causa del problema. Quello che vuoi è il CarNumber, Datainizio, ReturnDate, e UserId per questo record:

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.

Queste query selezionare l'assunto PK valori per le auto dei record che si intende per aggiornamento, la ricerca di automobili per i record corrispondenti con le attese di campi Chiave. Il mio denaro sarebbe che mentre il top query restituisce 1 record, il fondo query restituisce due righe, il significato, mentre solo 1 record è un #null ActualReturnDate valore, la tua Chiave non è abbastanza unico per il contenuto di questa tabella.

2021-11-26 22:57:48

sto usando contex, hai visto la mia schermata di stampa del modello di generatore?
elirans

Sì, ok che utilizza il DbContext del OnModelCreating modelBuilder, in modo che la Chiave è in fase di definizione. La prossima cosa da controllare è che le colonne corrispondono i PK /w vincolo univoco nel database corrispondente. Se non, che la chiave può avere bisogno di essere ampliato. Composito chiavi devono essere evitati, per quanto possibile, come fanno impostazione di relazioni molto più lavoro. È inoltre possibile utilizzare un profiler per acquisire la proposta di aggiornamento della dichiarazione, poi convertirla in una semplice SELECT per vedere quali file sono restituite. Per qualche motivo più righe sono di ritorno.
Steve Py

Un'altra cosa da controllare è se in fase di runtime dell'applicazione è di colpire lo stesso database, come quello che si sta verificando. I dati che si stanno verificando potrebbe apparire abbastanza unico se il DB non è imporre un vincolo di unicità su queste colonne, ma il database viene sottolineato in fase di runtime ha le righe duplicate.
Steve Py

stesso errore si verifica con la tua soluzione, ho bisogno di cambiare la mia funzione? @Steve Py
elirans

Catturare l'SQL generato ed eseguire sul database. Io in genere uso un Profiler per questo, quindi per SQL Server e sql server management studio, in Strumenti\SQL Profiler. Run che contro il tuo DB, quindi eseguire la query. È possibile utilizzare un punto di interruzione nella vostra applicazione appena prima che il SaveChanges, quindi deselezionare la profiler uscita prima di riprendere la pulizia del precedente rumore e trovare l'istruzione UPDATE.
Steve Py

Inoltre, puoi postare la tabella designer di uscita per il vostro tavolo? Il tavolo dispone di una vera PK set con quei 4 colonne?
Steve Py

Ho aggiunto alla risposta di cui sopra per includere misure per controllare la stringa di connessione nonché di verificare i dati se non vi sono i valori chiave.
Steve Py

Ho provato la tua soluzione. prima cosa si guarda come ti manca un po '=' in auto var. seconda cosa: quando cerco di fare l'aggiornamento: cars.ActualReturnDate = acctualDate1; ho ottenuto un errore cs1061.
elirans

In altre lingue

Questa pagina è in altre lingue

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