如何使用C# Linq优化嵌套循环并跨列表过滤,避免重复插入数据库
代码问题修复说明
你的代码存在以下核心问题,导致无法正常插入数据、也无法生效去重逻辑:
- 重复判断逻辑错误:
Where()方法返回的是查询集合对象,哪怕没有匹配数据也不会返回null,所以if(exist == null)判断永远不成立,自然不会走插入逻辑,需要用Any()方法判断是否存在匹配记录。 - 实体实例创建位置错误:你把
TaskList taskList = new TaskList();写在了循环外面,整个循环只会共用同一个实体对象,第一次插入后EF上下文已经跟踪了这个对象,后续修改属性再插入会直接报错,无法成功存库。 - DbSet名称拼写错误:上下文里的集合是
TaskLists,你代码里写成了db.taskList,拼写错误会直接抛出运行时异常,无法执行插入。 - 性能问题:循环内每次调用
SaveChanges()会频繁和数据库交互,效率极低,完全可以所有实体都添加完成后一次性提交。 - 冗余查询:开头定义的
addedtop变量没有被使用,你可以提前把所有已有的MemberId和Description组合查出来放内存,避免循环内每次查库,大幅提升执行效率。
修复后代码
// 提前查库拿到所有已存在的组合,避免循环内反复查库 var existingPairs = db.TaskLists.Select(a => new {a.MemberId, a.Description}).ToList(); // 扁平化笛卡尔积获取所有要插入的组合,原有写法逻辑正确无需修改 var membtasks = from m in members from n in tasks select new { MemberId = m, Description = n }; foreach (var item in membtasks) { // 先判断内存中是否已存在对应组合,不存在再新增 if (!existingPairs.Any(p => p.MemberId == item.MemberId && p.Description == item.Description)) { // 每次循环创建新的实体实例 var taskList = new TaskList() { Description = item.Description, MemberId = item.MemberId }; db.TaskLists.Add(taskList); // 同时把新增的组合加入内存集合,避免同批次插入重复数据 existingPairs.Add(item); } } // 一次性提交所有更改 db.SaveChanges(); return Redirect(url);
内容的提问来源于stack exchange,提问作者Diin
相关产品推荐
相关产品推荐

