“附加类型为X的实体失败,因为同一类型的另一个实体”在多个条目上出错

时间:2017-01-05 14:23:53

标签: c# entity-framework

我有这段代码:

               try
                {
                    newJob.Company = ((CustomPrincipal)HttpContext.Current.User).MyUser.WorkinCompany;

                    Random rnd = new Random();
                    newJob.JobId = rnd.Next(1000000, 10000000); 

                    realjob.RelatedJobs.Add(newJob);
                    _db.Entry(realjob).State = EntityState.Modified;
                }
                catch (Exception e)
                {

                }

我得到了这个例外:

  

附加“MySolution.Models.Register.MyUser”类型的实体   失败,因为同一类型的另一个实体已经相同   主键值。使用“附加”方法或时,可能会发生这种情况   将实体的状态设置为“未更改”或“已修改”(如果有)   图中的实体具有冲突的键值。这可能是因为   某些实体是新的,尚未收到数据库生成的密钥   值。在这种情况下,使用“添加”方法或“已添加”实体状态   跟踪图形,然后将非新实体的状态设置为   “视情况而定”或“修改”。

如何摆脱这种异常?感谢。

2 个答案:

答案 0 :(得分:0)

首先,你的随机函数rnd.Next(100000,1000000)将最终返回一个已经存在于你的数据库中的int(可能不是你使用它的前3次,但是过了一段时间,它确定)。

所以难怪你总是会遇到重复的主键异常。

然后,使用random不是为新实体生成主键的正确方法,请考虑以下选项:

  1. 查询表格以查找主键的最大值,并为其添加+1,如果它不存在,则输入1.

  2. 使用数据库集成的indentity列,只需添加没有主键的实体,主键将自动生成

答案 1 :(得分:0)

重复(?):

您的代码的其他[MAJOR]问题与您收到的错误没有直接关系,因为错误明确说明问题出在类DegerlemeTakip.Models.Register.MyUser ...

假设JobID是Job类的主键,将其设置为随机值并不是一个好主意。将JobID属性标记为生成的数据库,让DB担心设置密钥并删除将PK设置为随机值的行。

假设:

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

将您的代码更改为:

try
{
    newJob.Company = ((CustomPrincipal)HttpContext.Current.User).MyUser.WorkinCompany;

    realjob.RelatedJobs.Add(newJob);
    _db.Entry(realjob).State = EntityState.Modified;
}
catch (Exception e)
{
     //Please do something with the exception!
}

此外,不需要将realJob的状态设置为Modified。除非您有特定原因,否则请删除此行:

_db.Entry(realjob).State = EntityState.Modified;

如果必须随机设置JobID,则在尝试将JobID附加到数据上下文之前,需要检查以确保随机分配的JobID尚未使用:

    try
{
    newJob.Company = ((CustomPrincipal)HttpContext.Current.User).MyUser.WorkinCompany;

    Random rnd = new Random();
    newJob.JobId = rnd.Next(1000000, 10000000); 

    // Keep Trying Random JobIDs until one doesn't already exist in the database
    while(_db.Jobs.Any(j => j.JobID == newJob.JobID))
        newJob.JobId = rnd.Next(1000000, 10000000); 

    realjob.RelatedJobs.Add(newJob);
    _db.Entry(realjob).State = EntityState.Modified;
}
catch (Exception e)
{
     //Please do something with the exception!
}

上面的代码仍然存在重大问题,例如,一旦你在表中有9,000,000个作业,就没有剩余的ID可以分配,你的代码将永远循环,但你可以弄清楚,如果你绝对必须设置从代码中随机输入密钥。