我遇到使用EF Include()
缓存内存数据的问题。
var data = _context.Users
.Where(x => x.IsTrainee)
.GroupJoin(_context.Feedbacks.Include(x => x.User), u => u.UserId, f => f.AddedFor, (u, f) => new {u, f})
.ToList();
此处每个User
都有0到n Feedback
,每个反馈都有1-1 user
与之关联,使用FK AddedBy
。
当我使用foreach
迭代数据时,导航属性会被填满,我可以成功返回结果。
但是当我使用Parallel.ForEach
或.AsParallel().ForAll
时,Include()
对每个反馈都失败,User
Db集的导航属性Feedback
为{{ 1}}。
令人惊讶的是,上述并行操作并非每次都失败,有时会使用null
Feedback
来处理请求,但有时会返回User
。
null
但是当我添加上面的if (data.Any(r => r.f != null && r.f.Any(t => t.User == null)))
{
LogUtility.ErrorRoutine(new Exception("lastWeeklyFeedback is null:"));
}
块进行调试时,令我惊讶的是我的并行操作就像一个魅力。如果我评论上面的if
条件,那么并行操作就会很奇怪(即有时它有时会失败)。
我认为这与EF的if
有关。
为什么我的代码块会像这样?我缺少什么EF概念?。
注意:上述操作用于只读操作,不用于添加/更新数据库,只是为了获取数据。
修改
包括整个方法。条件和业务逻辑与上下文无关,但我添加了整个代码段以防万一你需要它。
Include
答案 0 :(得分:0)
这里发生了一些事情。首先,您正在GroupJoin的内部进行Include。你必须在ToList之前加入包含它或者它会丢失。
其次,源DbContext与Parallel.Foreach位于不同的线程上。我的直觉告诉我你已经开启了LazyLoading。当您遍历每个项目时,它正在执行数据库命中以加载它。但是,原始上下文是在不同的线程上。即使让你这样做,我也有点惊讶。但最终,当它贯穿时,我想它并不是在等待DbContext回来。现在,一些用户可能是共享的,所以最终有些用户会在之后回来并且能够正确映射而无需在DbContext中进行数据库调用。调试时,最终导致它等待的时间比正常情况要长,然后才能正确加载。