尝试更新现有记录时出现DbUpdateException

时间:2017-03-13 18:58:54

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

 using (var ctx = new Model.VMcontext())
        {
            List<Model.Process> Pr = new List<Model.Process>();
            Model.Process pp;
            foreach (RemoteProcess item in queueItem.rp)
            {
                pp = new Model.Process(item.ProcName, item.Procstatus, item.Timestamp, item.mcName);
                Pr.Add(pp);
            }


            VM vm = new VM(queueItem.VM_Hostname, queueItem.Disks ,queueItem.VMstatus, Pr);


            // compare vm object ref with current db objects 
            // If VM not present, insert VM

            VM DBvm = ctx.VirtualMachines.Find(vm.VM_Hostname);
            if (DBvm==null)
            {
                ctx.VirtualMachines.Add(vm);

            }
            // else VM exists so, update it [ERROR OCCURS HERE]
            else
            {

                //DBvm = vm;
                //ctx.Entry(vm).State = EntityState.Modified;   I tried various update methods too
                DBvm.disks = vm.disks;
                DBvm.Processes = vm.Processes;
                DBvm.VMstatus = vm.VMstatus;

            }

            ctx.SaveChanges();
        }

当我更新现有记录时,会抛出异常。我在这里查找了其他答案,但似乎没有任何帮助。

类型&#39; System.Data.Entity.Infrastructure.DbUpdateException&#39;的例外情况发生在EntityFramework.dll中但未在用户代码中处理

其他信息:更新条目时发生错误。有关详细信息,请参阅内部异常。

哪里出错了?

修改 正如所建议的那样,查看内部异常,它说我试图插入一个重复的值&#39; C:&#39;进入磁盘表。但我没有插入任何数据,我只是找到现有的记录并更新它。我不确定如何获得主键重复错误*

编辑2

public class VM
{
    public VM(string host,List<Disk>d ,int stat,List<Process> procs)
    {
        VM_Hostname = host;
        disks = d;
        VMstatus = stat;
        Processes = procs;
    }

    public VM() { }

    [Key]
    public string VM_Hostname { get; set; }
    public int VMstatus { get; set; }
    public virtual ICollection<Model.Process> Processes { get; set; }
    public virtual List<Disk> disks { get; set; }
}

public class Process
{
    public Process(string pname,int stat,DateTime d, string vm )
    {
        ProcessName = pname;
        status = stat;
        date = d;
        VM_hostname = vm;
    }

    public Process() { }

    [Key]
    public string ProcessName { get; set; }
    public int status { get; set; }
    public DateTime date { get; set; }

    public string VM_hostname { get; set; }

    [ForeignKey("VM_hostname")]
    public virtual Model.VM vm { get; set; }
}

 public class Disk
{

    [Key]
    public string name { get; set; }
    public double freeSpace { get; set; }
    public double freePercent { get; set; }
    public double totalSpace { get; set; }
    public double used { get; set; }
    public string VM_hostname { get; set; }

    [ForeignKey("VM_hostname")]
    public virtual Model.VM vm { get; set; }
}

1 个答案:

答案 0 :(得分:0)

正如我在评论中提到的,您的问题是您正在使用在创建当前上下文之前创建的DiskProcess对象的列表。因此,上下文不知道它们,当您替换Disk实体上的ProcessVM对象列表时,上下文假定它们都是新项目,并尝试将它们添加到数据库中。但由于它们不是新项目,因此存在导致您看到异常的主要冲突。

要解决您的问题,您需要在保存之前将DiskProcess个对象附加到您的上下文中。

E.g:

VM DBvm = ctx.VirtualMachines.Find(vm.VM_Hostname);
if (DBvm==null)
{
    ctx.VirtualMachines.Add(vm);

}
// else VM exists so, update it [ERROR OCCURS HERE]
else
{

    //DBvm = vm;
    //ctx.Entry(vm).State = EntityState.Modified;   I tried various update methods too
    foreach (var disk in vm.disks)
    {
        //Only attach if the entity already exists, otherwise just let it get added.
        if (ctx.Disks.Find(disk) != null) 
        {
            ctx.Disks.Attach(disk);
            ctx.Entry(disk).State = EntityState.Modified;
        }
    }
    foreach (var process in vm.Processes)
    {
        if (ctx.Processes.Find(process) != null)
        {
            ctx.Processes.Attach(process);
            ctx.Entry(process).State = EntityState.Modified;
        }
    }
    DBvm.disks = vm.disks;
    DBvm.Processes = vm.Processes;
    DBvm.VMstatus = vm.VMstatus;

}

添加用于附加实体的循环应解决异常,因为它告诉上下文有关这些对象,并将其状态设置为已修改意味着它们不是新的,应该更新,而不是插入。