如何在EF Core中正确更新数据行?(基于现有上下文的foreach场景)
最优解决方案
方案一:初始查询时跟踪实体(推荐)
你当前的查询是投影到DebtCollectionList这个DTO对象,EF Core不会跟踪这类非实体类型的对象,所以直接修改DTO无法同步到数据库。最优方式是调整初始查询,同时保留被EF Core跟踪的Transaction实体,这样处理业务后可直接修改实体字段,最后统一提交更改,避免额外数据库查询。
代码示例:
// 查询时同时获取跟踪的Transaction实体和映射后的DTO var transactionData = _context.Transactions .Where(x => x.Status == 0 && x.TransactionDate <= compareDate && !x.Processed) .Select(x => new { Transaction = x, // 保留被上下文跟踪的实体 DebtCollection = new DebtCollectionList { transaction_id = x.TransactionId, iin_pan = x.IinPan, transaction_date = (DateTime)x.TransactionDate, amount = (decimal)x.Amount } }) .ToList(); // 遍历处理业务并更新实体 foreach (var item in transactionData) { // 这里写你的业务处理逻辑,比如处理item.DebtCollection // ... // 直接修改跟踪的实体字段 item.Transaction.Processed = true; } // 统一提交所有更改到数据库 _context.SaveChanges();
方案二:通过DTO的ID查找实体(适配无法修改初始查询的场景)
如果不能调整初始的DTO查询,可在循环中利用transaction_id,通过上下文的Find方法(优先查询内存缓存,再查数据库)获取对应Transaction实体,修改后批量提交。
代码示例:
foreach (var debt in debtCollections) { // 这里写你的业务处理逻辑 // ... // 根据ID查找对应的跟踪实体 var transaction = _context.Transactions.Find(debt.transaction_id); if (transaction != null) { transaction.Processed = true; } } // 一次性提交所有更改 _context.SaveChanges();
关键注意点
- 不要在循环内每次调用
SaveChanges,会产生多次数据库交互,大幅降低性能,建议批量修改后统一提交。 - 若数据量极大,可分批次处理并提交,避免内存占用过高。
内容的提问来源于stack exchange,提问作者Jason_Hough
相关产品推荐
相关产品推荐

