简体   繁体   中英

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'Database operation expected to affect 1 row(s) but actually affected 2 row(s)

I received this error once I try to update table with the same value (carNumber), my condition is to update where the actual return date field is null.

For some reason it's look like the query return 2 rows, but actually there is only one. I'm using EF. This is the function:

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

The error raise when trying to db.saveChanges()

the table from the db, the car number is 1000 - print screen

modelBuilder.Entity pic

please let me know how can I solve this issue.

This error occurs when EF cannot resolve the PK for your entity. In most cases for simple entities, EF conventions can work out the PK, but in your case you are using a composite key so this needs to be configured. Depending on how you are mapping your entities you can do this either in:

  • an EDMX
  • in the DbContext.OnModelCreating
  • using an EntityTypeConfiguration declaration
  • using attributes within the entity itself

Since we don't know how your entities are configured, you can verify this as the cause by using the attribute approach within your entity as a test. If you are using an EDMX the entity classes will be generated so you will want to replace this with configuration within the EDMX. (Cannot really help you there because I don't use the dang things:D )

You will probably have something like:

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

You may even have a [Key] attribute on one of these fields, such as CarNumber. If there is a PK mapped in the entity the issue is that it isn't specific enough to uniquely identify the row. When EF goes to update one entity, it is checking for, and expecting to update only one row in the table. It's finding more than one row will be affected so it fails.

Append the attributes for the [Key] with the column order so it is recognized as a composite key.

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

Provided these 4 columns are guaranteed to be a unique constraint on the table, EF will be satisfied when only one row is updated when it builds it's UPDATE SQL statement.

Note again that if this works and you are using an EDMX, you will need to review and modify your EDMX mapping to make the appropriate changes since that entity class could be regenerated, losing your extra attributes. (I believe the generated entity classes from an EDMX have a comment header warning you that it is a generated class, so that is an indicator to watch out for.)

problem solved by add a new column to the car_rental_fields table, id column that include Identity. as I understand from here and from the web, there is an issue with complicated pk. in my solution the id isn't a primary key, but it's make the logic for linq to update the correct column. thanks' for all the people that involved in this issue.

EF generates sql query like this

update carfields SET  retdate = @retdate  WHERE 
car_number = @car_number and userId=@u.. 
and date1 = @date1 and date2=@date2

Since you have so complicated ( speaking softly) primary key that includes dates, it can easily select 2 rows instead of one.

IMHO To prevent this kind of problem in the future, you should take the thougt about excluding dates from your PK or maybe it is much better to use just common autoincrement key and create an unique index at all another columns.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM