.NET 5 API项目staging环境报Collection was modified枚举执行错误
根因分析
你遇到的System.InvalidOperationException: Collection was modified; enumeration operation may not execute.属于典型的枚举集合过程中集合内容被修改抛出的异常,触发点就是代码里LINQ查询join操作的左值video.Tags.Select(x => x.TopicId)。
仅staging环境复现的原因
- 本地、开发环境数据量小,LINQ执行速度快,不会出现枚举期间集合被修改的时间窗口;staging环境数据量更大,EF生成、执行SQL的耗时更长,而
video.Tags.Select(x => x.TopicId)是延迟执行的LINQ查询,EF执行整个关联查询时才会真正枚举video.Tags集合,此时如果集合被修改就会触发报错。 - 最常见的修改来源是你先调用的
_mapper.Map<VideoDetailsResponse>(video)逻辑:如果AutoMapper配置中存在修改原始video对象Tags集合的规则(比如AfterMap操作、集合属性的双向绑定配置等),staging环境的运行时时序下,Mapper的修改逻辑刚好和EF枚举Tags的逻辑重叠,就会触发报错,本地因为执行速度快不会触发这个时序问题。
修复方案
只需要把LINQ查询中用到的内存集合提前固化,避免延迟枚举即可,修改items的查询逻辑,将video.Tags.Select(x => x.TopicId)提前转为独立的List:
// 提前枚举TopicId生成固定List,避免后续查询时延迟枚举被修改的Tags集合 var topicIds = video.Tags.Select(x => x.TopicId).ToList(); var items = (from topicId in topicIds join tag in _context.VideoTagLink on topicId equals tag.TopicId join videoItem in _context.Videos .Include(x => x.CreatedByUser) .Include(x => x.Like) .Include(x => x.PublishedByUser) .Include(x => x.ModifiedByUser) .Include(x => x.Tags) .ThenInclude(x => x.Topic) .Include(x => x.AdminTags) .ThenInclude(x => x.AdminTag) .Where(x => !x.IsDeleted && !x.IsHidden) on tag.VideoId equals videoItem.Id where tag.VideoId != id && !videoItem.IsDeleted select videoItem).Take(2).ToList();
额外优化建议
- 排查AutoMapper的映射配置,避免映射操作修改原始的EF实体对象,防止后续其他业务逻辑出现类似的意外修改问题。
- 可以将关联视频的查询逻辑改为纯数据库侧查询,避免内存集合和数据库IQueryable混用做join,降低EF生成低效SQL的概率。
内容的提问来源于stack exchange,提问作者Anil Kumar
相关产品推荐
相关产品推荐

