【问题标题】:EF6 Cannot insert duplicate key rowEF6 无法插入重复的键行
【发布时间】:2016-03-18 01:33:55
【问题描述】:

当我尝试使用唯一约束更新实体时出错 我检查了表格,有几个类似的帖子,但没有一个答案。

    public class Car
    {
         [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int IdCar { get;set; }

        public string ColorCode { get; set; }

        [Index(IsUnique = true)]
        public string MotorId { get; set; }
    }

     private static int UpsertCar(Car checkCar, IUow uow)
    {
        var car =
           uow.Cars.GetAll().FirstOrDefault(x => x.MotorId.Trim()
               .Equals(checkCar.MotorId.Trim(),
                   StringComparison.CurrentCultureIgnoreCase));

        if (car == null)
        {
            uow.Cars.Add(checkCar);
            uow.Commit();
            return checkCar.IdCar;
        }
        else
        {
            car.ColorCode = checkCar.ColorCode;
            uow.Cars.Update(car);
            uow.Commit(); // Issue when i try to save
            return car.IdCar;
        }
    }

这里是更新函数

 public virtual void Update(T entity)
    {
        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State == EntityState.Detached)
        {

            DbSet.Attach(entity);
        }  
        dbEntityEntry.State = EntityState.Modified;
    }

错误

无法在具有唯一索引“IX_MotorId”的对象“dbo.Car”中插入重复的键行。 该语句已终止。

【问题讨论】:

  • 更新时使用car 实例而不是checkCar
  • 为什么你在找车的时候检查的是MotorId而不是IdCar(BTW很奇怪的命名方式)?
  • 命名不是问题,这是应用程序的逻辑

标签: c# sql-server entity-framework inversion-of-control repository-pattern


【解决方案1】:

这里的问题是您选择在实体框架之上使用存储库模式 - 一个架构问题。这不是您的解决方案中唯一会遇到的问题。

EF6 非常强大,而存储库模式隐藏了所有这些功能。

编码整个 upsert 概念的标准方法是从上下文加载原始记录:

public class Car
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int IdCar { get;set; }

    public string ColorCode { get; set; }

    [Index(IsUnique = true)]
    public string MotorId { get; set; }

    //By having this update function alongside the members, it's easy to see whether it's up to date.
    public void Update(Car original)
    {
        original.ColorCode = ColorCode;
        original.MotorId = MotorId;
    }
}

public static int UpsertCar(Car checkCar, MyContext db)
{
    var original = db.Cars.SingleOrDefault(c => c.IdCar == checkCar.IdCar);

    if (original == null)
    {
        db.Cars.Add(checkCar);
    }
    else
    {
        checkCar.Update(original);
    }
    db.SaveChanges();
}

在这里你可以看到直接使用EntityFramework是多么的简单。

重要的是,您还可以看到创建自己的更新函数是多么简单(保持当前的 ORM 架构)。通常,业务规则会限制可以更新的内容,而您自己的更新函数将不允许更新所有字段。

您永远不需要使用dbEntityEntry.State = EntityState.Modified;,如果这样做,您可能会错误地处理代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 2016-02-11
    • 2020-11-27
    • 2021-06-30
    相关资源
    最近更新 更多