zoukankan      html  css  js  c++  java
  • 陷阱~EF中的Update与Insert共用一个数据上下文

    事情是这样的,有一个列表,里面有很多用户信息,可能会有重复的用户,将这个列表的用户插入到数据表中,如果用户已经存在,就更新这个用户的FillTimes 字段,让它加1,使用的底层ORM是entity frameworks4。

    这是方法的大概内容

                var user_Account = iC_User_Account.Find(i => i.UserID == u.UserID);
                if (user_Account == null)
                {
                    iRepository.Insert(new C_User_Account 
                    {
                        AccountID = 1,
                        AddTime = rechargeTime,
                        BeginDate = rechargeTime,
                        EndDate = rechargeTime.AddYears(100),
                        FillTimes = 1,
                        Income = 0,
                        Incoming = 0,
                        LockMoney = 0,
                        Outgoings = card.CardValue,
                        Status = 1,
                        UserID = u.UserID,
                        UserType = 1,
                    });
                }
                else
                {
                
                    user_Account.FillTimes = user_Account.FillTimes ?? 0 + 1;
                    iRepository.Update(user_Account);
                }

    这个方法看似没有任何问题,当一个用户没有在表中存在,就insert,如果存在了,就update,这是再简单不过的逻辑了,然而,如果你的iRepository对象声明

    放错了位置,可能问题就出来了,我们知道DbContext是有缓存的,当一个实体被提交后,它可能在缓存里还会存在,直到DbContext被dispose之后,它才会

    消失,这就是说,如果insert与update使用的是同一个DbContext,就会出现一个异常,“不能在相同的对象上建立新实体”,而一般地,insert与update不能不同存在,这是我们可以想像的,而我们可能往往忽略了DbContext是否为一个,如果insert或者update之后,DbContext对象没有被销毁,那异常就会出现了。

    而在本例中,iRepository的声明与实例化是在方法体外部完成的,而这个方法就是在被集合遍历时调用的,这时,你的iRepository里的DbContext对象就成了一个,在这个方法的生命周期时,你的数据上下文是一个,你的update操作也就出现问题了,呵呵。

    //定义一个数据操作对象
    var iRepository=new Repository<User>();
    
    //供外部调用的更新用户列表的方法
    public void UpdateUser(List<User> list)
    {
      userList.ForEach(i=>{
         InsertOrUpdateUser(i);
     });
    }

    如果你的代码是这样写的话,那在遍历调用 InsertOrUpdateUser方法时,就有可能出现上面的异常了,呵呵!

    正确的作法是将var iRepository=new Repository<User>();这句话移到InsertOrUpdateUser方法体里,问题就解决了。

  • 相关阅读:
    u盘重装ubuntu16.04过程遇到的问题
    CTC安装及其错误解决办法:binding.cpp:92:49: error: cannot convert ‘THCudaTensor*’ to ‘const THFloatTensor*’ for argument ‘1’ to ‘int64_t THFloatTensor_size(const THFloatTensor*, int)’
    CTC安装错误之:binding.cpp:6:29: fatal error: torch/extension.h: No such file or directory
    机器学习入门(1)
    python学习笔记(1)
    python学习笔记(1)
    rpm命令的简介-(转自jb51.net )
    centos下安装visual studio code-(来自官网)
    ubuntu中安装visual studio code-(转载)
    git使用简单教程-(转自linux人)
  • 原文地址:https://www.cnblogs.com/lori/p/3267764.html
Copyright © 2011-2022 走看看