繁体   English   中英

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:'数据库操作预计会影响 1 行,但实际上会影响 2 行

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

一旦我尝试使用相同的值(carNumber)更新表,我就会收到此错误,我的条件是更新实际返回日期字段为 null 的位置。

出于某种原因,查询返回 2 行,但实际上只有 1 行。 我正在使用EF。 这是 function:

错误 - 打印屏幕

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

尝试 db.saveChanges() 时出现错误

db 中的表,车号为 1000 - 打印屏幕

modelBuilder.Entity 图片

请让我知道如何解决这个问题。

当 EF 无法为您的实体解析 PK 时会发生此错误。 在大多数情况下,对于简单实体,EF 约定可以计算出 PK,但在您的情况下,您使用的是复合键,因此需要对其进行配置。 根据您映射实体的方式,您可以通过以下方式执行此操作:

  • EDMX
  • 在 DbContext.OnModelCreating
  • 使用EntityTypeConfiguration声明
  • 在实体本身中使用属性

由于我们不知道您的实体是如何配置的,您可以通过使用实体中的属性方法作为测试来验证这一点。 如果您使用的是 EDMX,则会生成实体类,因此您需要将其替换为 EDMX 中的配置。 (不能真正帮助你,因为我不使用该死的东西:D)

你可能会有类似的东西:

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

您甚至可以在这些字段之一上具有[Key]属性,例如 CarNumber。 如果实体中映射了 PK,则问题是它不够具体,无法唯一标识该行。 当 EF 去更新一个实体时,它正在检查并期望只更新表中的一行。 它发现不止一行会受到影响,因此它会失败。

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

如果保证这 4 列是表上的唯一约束,则 EF 在构建它的 UPDATE SQL 语句时仅更新一行时将得到满足。

再次注意,如果这有效并且您使用的是 EDMX,您将需要查看并修改您的 EDMX 映射以进行适当的更改,因为该实体 class 可能会重新生成,从而丢失您的额外属性。 (我相信从 EDMX 生成的实体类有注释 header 警告您它是生成的 class,因此这是一个需要注意的指标。)

通过向 car_rental_fields 表中添加一个新列来解决问题,id 列包含身份。 正如我从这里和 web 了解的那样,复杂的 pk 存在问题。 在我的解决方案中,id 不是主键,但它使 linq 更新正确列的逻辑。 感谢所有参与此问题的人。

EF 像这样生成 sql 查询

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

由于您具有包含日期的如此复杂(轻声说)的主键,因此它可以轻松 select 2 行而不是 1 行。

恕我直言,为了防止将来出现此类问题,您应该考虑从 PK 中排除日期,或者最好只使用通用的自动增量键并在所有其他列上创建唯一索引。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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