如何使用Entity Framework Core实现多表关联批量更新多行数据
Entity Framework Core 关联更新ProjectStep表ParentStepId实现方案
优先方案(EF Core 7.0及以上版本,纯Linq写法,性能最优)
EF Core 7开始提供了ExecuteUpdate/ExecuteUpdateAsync方法,支持直接在数据库端执行批量更新,生成的SQL逻辑和你手写的原生SQL一致,无需加载数据到内存:
// 假设context为你的DbContext实例 await context.ProjectSteps // 关联StepDefinition表 .Join( context.StepDefinitions, ps => ps.StepDefinitionId, sd => sd.StepDefinitionId, (ps, sd) => new { CurrentPs = ps, Sd = sd } ) // 关联父级ProjectStep表 .Join( context.ProjectSteps, joinItem => joinItem.Sd.ParentStepId, parentPs => parentPs.StepDefinitionId, (joinItem, parentPs) => new { joinItem.CurrentPs, NewParentStepId = parentPs.ProjectStepId } ) // 此处可追加你原SQL中省略的过滤条件,示例:.Where(x => x.CurrentPs.ProjectId == xxx) .ExecuteUpdateAsync(setters => setters .SetProperty(x => x.CurrentPs.ParentStepId, x => x.NewParentStepId) );
EF Core 6.0及更低版本方案
方案1:小数据量适用(内存加载后更新,Linq写法)
如果需要更新的数据量不大,可以先查询出匹配数据,遍历赋值后统一保存:
var updateList = await context.ProjectSteps .Join( context.StepDefinitions, ps => ps.StepDefinitionId, sd => sd.StepDefinitionId, (ps, sd) => new { CurrentPs = ps, Sd = sd } ) .Join( context.ProjectSteps, joinItem => joinItem.Sd.ParentStepId, parentPs => parentPs.StepDefinitionId, (joinItem, parentPs) => new { joinItem.CurrentPs, NewParentStepId = parentPs.ProjectStepId } ) // 此处追加过滤条件 .ToListAsync(); foreach (var item in updateList) { item.CurrentPs.ParentStepId = item.NewParentStepId; } await context.SaveChangesAsync();
方案2:大数据量适用(原生SQL执行,性能最优)
如果更新数据量较大,可直接执行你现有的SQL语句,避免内存开销:
// 有参数时建议使用ExecuteSqlInterpolatedAsync防止SQL注入 var affectedRows = await context.Database.ExecuteSqlRawAsync(@" UPDATE ps SET ParentStepId=ps1.ProjectStepId FROM ProjectStep ps INNER JOIN StepDefinition sd ON ps.StepDefinitionId = sd.StepDefinitionId INNER JOIN ProjectStep AS ps1 ON sd.ParentStepId = ps1.StepDefinitionId -- 此处追加你的额外过滤条件 ");
内容的提问来源于stack exchange,提问作者Sonja
相关产品推荐
相关产品推荐

