Ef's。包含ParallelFor

时间:2017-03-16 08:28:35

标签: c# entity-framework parallel-processing entity-framework-6 asp.net-4.5

我遇到使用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

1 个答案:

答案 0 :(得分:0)

这里发生了一些事情。首先,您正在GroupJoin的内部进行Include。你必须在ToList之前加入包含它或者它会丢失。

其次,源DbContext与Parallel.Foreach位于不同的线程上。我的直觉告诉我你已经开启了LazyLoading。当您遍历每个项目时,它正在执行数据库命中以加载它。但是,原始上下文是在不同的线程上。即使让你这样做,我也有点惊讶。但最终,当它贯穿时,我想它并不是在等待DbContext回来。现在,一些用户可能是共享的,所以最终有些用户会在之后回来并且能够正确映射而无需在DbContext中进行数据库调用。调试时,最终导致它等待的时间比正常情况要长,然后才能正确加载。