• EntityFramework 4.x 使用中遇到的问题 (1)


    在目前项目里,使用Code First的模式,但数据库已经存在,并且在数据库中并未设立外键关系,但在实体类中定义了实体关系。以上为这次遇到问题的背景。

    问题:

    在保存一组数据的时候,提示出现主键重复的问题。

    相关代码:

    Dictionary<<Tuple<string, int>, Detail> details = ... // 该数据有方法外部传入
    if(order.Details != null) // Order对象包含一个Detail对象的列表
    {
        foreach(var d in order.Details.ToArray())
        {
             var key = Tuple.Create(d.Id, d.No);
             if(details.ContainKey(key))
             {
                  // update the records with new value
                  details.Remove(key);
             }
             else
             {
                  dbContext.Entry(d).State = EntityState.Deleted;
             }
        }
        foreach(var d in details.Values)
        {
             dbContext.Details.Add(d);
        }
        dbContext.SaveChanges();
    }
    

      

    问题定位:

    首先根据异常,找出引起错误的数据,发现要保存的数据并不存在重复情况,同时在数据库里存在该数据,按理说不应出现这个错误。

    根据Log无法发现问题,只好调试程序了。当程序执行到var order = dbContext.Order.Find("id")的时候,发现数据库并不存在该id的数据,代码执行到这里,大概就已经发现了问题所在。由于数据里并不存在该id的数据,所以在前面Find的代码执行完毕后,根据输入的order数据创建了一个新的Order对象,这个时候,order的State是Added状态。当entry处于该状态时,在访问导航属性的时候,并不会尝试去数据库里读取Detail数据,所以执行上面的代码的时候,实际上是执行的dbContext.Details.Add(d)的部分。这也就造成了提示主键重复的异常。

    解决:

    既然是导航属性造成的问题,就只好选择绕开导航属性,直接通过Linq将Order数据读出来。

    Dictionary<<Tuple<string, int>, Detail> details = ... // 该数据有方法外部传入
    var detailsInDb = (from item in dbContext.Details where item.Id == order.Id select item).ToArray();
    if(detailsInDb != null)
    {
        foreach(var d in detailsInDb)
        {
             var key = Tuple.Create(d.Id, d.No);
             if(details.ContainKey(key))
             {
                  // update the records with new value
                  details.Remove(key);
             }
             else
             {
                  dbContext.Entry(d).State = EntityState.Deleted;
             }
        }
        foreach(var d in details.Values)
        {
             dbContext.Details.Add(d);
        }
        dbContext.SaveChanges();
    }
    

      

  • 相关阅读:
    【剑指offer】面试题35:第一个只出现一次的字符
    【剑指offer】面试题34:丑数
    【剑指offer】面试题33:把数组排成最小的数
    【剑指offer】面试题32:从1到n整数中1出现的次数
    【剑指offer】面试题31:连续子数组的最大和
    【剑指offer】面试题30:最小的 k 个数
    【剑指offer】面试题29:数组中出现次数超过一半的数字
    【剑指offer】面试题28:字符串的排列
    【剑指offer】面试题27:二叉搜索树与双向链表
    【剑指offer】面试题26:复杂链表的复制
  • 原文地址:https://www.cnblogs.com/FMax/p/2455985.html
Copyright © 2020-2023  润新知