业务场景:
实际业务场景比较复杂,简单举个相似的例子
1、A表(提问表)结构:
(Id,Title(标题),DefaultValue(默认答案) );
5个问题 5条记录
2、B表(答案表)结构:
(Id,user_Id(用户编号), A_Id(A表的问题编号),Value(答案) );
一个用户 5个问题对应的5个答案
3、前端页面需要提取某个指定的用户答案列表:
[ B_Id,A_Title,B_Value ]
由于需要的这3个字段结构 刚好跟A表的结构吻合
于是想直接 提取A表数据,然后补充5个问题答案到 DefaultValue字段 返回前端
public async Task<A> GetAsync()
{
//1、提取5个问题列表
var tmpALst = _repositoryA.GetAll().ToList();
//2、提取9527用户的5个狗屁答案
var tmpBLst = _repositoryB.GetAll().Where(p => p.user_Id = 9527).ToList();
//3、循环问题列表 填充用户答案到DefaultValue
tmpALst.ForEach(e =>
{
var tmpAnswer = tmpBLst.Find(p => p.A_Id == e.Id);//找打A记录Id 对应的B表答案
if (tmpAnswer != null)
{
//把用户答案直接补充到 A表问题记录的 defaultvalue中,此处只是一个取巧的操作,主要用于达意
e.DefaultValue = tmpAnswer.Value;
}
});
return tmpALst; //返回结果
}
陨石坑悄然来了:
这个方法执行后前端一切正常,看起来没有任何问题,但是数据库表A对应的DefaultValue就跟着自动更新成了实际的用户答案,又没有任何update更新操作
由于实际业务逻辑比较复杂,排查了好久才发现上面黄字问题内容,主要是因为ABP底层架构有自动跟踪数据变更的功能,所有从数据库提取的记录,改变后ABP都会自动进行数据更新…
解决方案:
在查询数据库数据的时候 取消跟踪:.AsNoTracking()
public async Task<A> GetAsync()
{
var tmpALst = _repositoryA.GetAll().AsNoTracking().ToList();
var tmpBLst = _repositoryB.GetAll().Where(p => p.user_Id = 9527).ToList();
*****************************************
return tmpALst; //返回结果
}
小结:
虽然问题出现的时候,感觉毫无道理,百撕不得骑姐,但是最终还是论证了一个天理:
出了问题首先态度要端正,一定要相信肯定是自己的错,然后扪心自问我特么到底错哪里了,千百轮回的扪心自问虽然感动不了测试的妹子,但你一定能感动自己,也许更多的时候是被自己蠢哭…
有朋自远方来 虽远必诛,欢迎加微交流: 15249207822