EF6 无法插入重复的键行

Posted

技术标签:

【中文标题】EF6 无法插入重复的键行【英文标题】:EF6 Cannot insert duplicate key row 【发布时间】: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很奇怪的命名方式)? 命名不是问题,这是应用程序的逻辑 【参考方案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;,如果这样做,您可能会错误地处理代码。

【讨论】:

以上是关于EF6 无法插入重复的键行的主要内容,如果未能解决你的问题,请参考以下文章

无法在具有唯一索引的对象中插入重复的键行

具有过滤索引的实体框架 - “无法在对象中插入重复的键行”

无法在具有唯一索引“IX_ta_Kullanici”的对象“dbo.ta_Kullanici”中插入重复的键行。\r\n语句已终止

在具有标识列的表中插入 select from

统计HIVE字段行数NULL行数字段重复行数

统计HIVE字段行数NULL行数字段重复行数