最近公司项目需要,想要给订单增加一个状态修改记录。
说起来很简单的需求,但是做的时候,卡了我半天。。。
问题描述:
修改订单状态保存之前的时候,需要判断,如果新状态不等于旧状态,才做记录,但是在底层的Repository里写判断的时候,获取的状态始终相同,并没有能获取到数据库的最新数据。
问题调查:
经过研究和试验,发现这个ef的特殊机制。
就是服务器经过单实例操作后,所有的客户端使用的数据集是一个,虽然是new出来的实例,但是只是开了一个线程而已。所以所有人用的都是一个数据集(一个DBContainer)。
/// <summary> /// 获取当前线程的数据上下文 /// </summary> /// <returns>数据上下文</returns> public static DBContainer CurrentContext() { DBContainer _nContext = CallContext.GetData(ConfigPara.EFDBConnection) as DBContainer; if (_nContext == null) { _nContext = new DBContainer(); CallContext.SetData(ConfigPara.EFDBConnection, _nContext); } return _nContext; }
那么这里的数据就有个说法了。
public virtual bool Edit(T model) { if (db.Entry<T>(model).State == EntityState.Modified) { int i = 0; try { i = db.SaveChanges(); } catch (Exception ex) { return false; } return i > 0; } else if (db.Entry<T>(model).State == EntityState.Detached) { try { db.Set<T>().Attach(model); db.Entry<T>(model).State = EntityState.Modified; } catch (InvalidOperationException) { //T old = Find(model._ID); //db.Entry<old>.CurrentValues.SetValues(model); return false; } return db.SaveChanges()>0; } return false; }
数据的修改,创建最终调用的方法是db.savechanges(),也就意味着,所有的改动,都是先存放在这个container对象中,这里有个大的set。只要调用了db.savechanges(),自然会把所有的改动一起提交。
所以这里的问题是想判断新保存的状态和原状态是否相同的时候,就不能使用这一个container了。
解决办法
在需要判断的地方,重新new一个container出来
//这里必须这么写,不然的话,用获取的那个ef实体,得到的集合里的这个对象已经是改变的了,虽然没保存 DBContainer dBContainer = new DBContainer();var order = (from r in dBContainer.PaasOLT_Order where r.Id == model.Id select r).First();
这种方法获取出来的实体就是一个新的了,不受原来的container的约束了。自然可以获取到最新的数据库的数据了。