ObjectContext在EF 6中使用.AddRange时出错

时间:2016-02-17 18:07:24

标签: c# entity-framework entity-framework-6

我正在尝试在EF 6中使用.AddRange时遇到的错误找到一些帮助。我收到以下错误。

The changes to the database were committed successfully, but an error occurred while updating the object context. 
The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because 
the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are 
unique before calling AcceptChanges.

正如错误所述,我的记录实际上已添加到表中,因此我不知道修复错误的位置。

进行一些研究我发现了很多帖子,其他人说它与.edmx文件和桌面上的主键有关。他们的建议基本上是添加PK然后重建.edmx文件。这不符合我的情况有两个原因,一个是我使用EF 6和DataBase First所以没有.edmx文件,第二个是它被映射到Oracle 11 DB并因此创建了身份带有触发器(当我查看添加的记录时,它似乎有效)。

这是我正在使用的代码以及实体的类。

using (APIcontext db = new APIcontext())
            {
                if (listLostTime.Count > 0)
                {
                    db.GROUND_HOURS.AddRange(listLostTime);
                    db.SaveChanges();
                }
            }

实体类

[Table("GROUND_HOURS")]
    public partial class GROUND_HOURS
    {
        [Key]
        public decimal RID { get; set; }

        [Required]
        [StringLength(8)]
        public string EMP_ID { get; set; }

        [StringLength(2)]
        public string COMPANY_CODE { get; set; }

        public DateTime OCCURRENCE_DATE { get; set; }

        [Required]
        [StringLength(25)]
        public string PAY_CODE { get; set; }

        public decimal PAY_HOURS { get; set; }

        public DateTime INSERT_DATE { get; set; }
    }

我正在寻找任何建议。

2 个答案:

答案 0 :(得分:2)

使用属性RID

装饰DatabaseGenerated( DatabaseGeneratedOption.Identity )属性

问题是实体框架在接受更改之前没有使用商店生成的值更新键值RID。在您的情况下,创建了多个GROUND_HOURS实体,每个实体都会(默认)默认RID值为0.当EF尝试接受更改时,它会识别出多个实体具有相同的键值抱怨。

答案 1 :(得分:0)

感谢@Moho给出了最终解决方案。这就是我将实体类中的主键更改为工作的方式,也是我在应用程序中使用的方法。

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

我还能够以另一种方式修复它,只是为了让别人知道。首先,因为这是和Oracle DB RID(这是我的主键)是一个十进制的脚手架。当我将对象添加到列表而没有专门为其赋值时,这导致RID始终为0。为了解决这个问题,我将RID属性更改为可以为空的INT,然后在创建列表时设置RID = NULL。

[Key]
public int? RID { get; set; }

这就是我在创建列表时所做的。

foreach (var item in results)
{
GROUND_HOURS lostTime = new GROUND_HOURS();
lostTime.RID = null;
lostTime.EMP_ID = item.EmployeeId.ToString("D8");
lostTime.COMPANY_CODE = item.CompanyCode.Trim();
lostTime.OCCURRENCE_DATE = item.OccurrenceDate;
lostTime.PAY_CODE = item.PayCode.Trim();
lostTime.PAY_HOURS = item.Hours;

listLostTime.Add(lostTime);
}