EF Core事务:HierarchyId节点迁移的C#等价实现问询
EF Core中实现HierarchyId节点迁移的事务代码(等价于官方存储过程)
需求背景
原本使用微软官方提供的SQL存储过程实现HierarchyId节点迁移,现需改用EF Core的C#事务代码实现完全等价的逻辑,替代直接调用存储过程。
等价C#实现代码
首先确保项目已安装Microsoft.EntityFrameworkCore.SqlServer和Microsoft.EntityFrameworkCore.SqlServer.HierarchyId NuGet包,且EmployeeDemo实体已正确映射数据库表:
// EmployeeDemo实体示例 public class EmployeeDemo { public string LoginID { get; set; } public SqlHierarchyId OrgNode { get; set; } // 其他业务属性... }
迁移逻辑的C#方法:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.SqlServer.Types; public async Task MoveOrgAsync(string oldMgrLoginId, string newMgrLoginId) { // 开启Serializable级别的事务,和原存储过程保持一致 using var transaction = await _dbContext.Database.BeginTransactionAsync(IsolationLevel.Serializable); try { // 获取旧管理者的HierarchyId节点 var oldOrgNode = await _dbContext.EmployeeDemo .Where(e => e.LoginID == oldMgrLoginId) .Select(e => e.OrgNode) .FirstOrDefaultAsync(); if (oldOrgNode == null) throw new InvalidOperationException("未找到指定的旧管理者"); // 获取新管理者的HierarchyId节点 var newOrgNode = await _dbContext.EmployeeDemo .Where(e => e.LoginID == newMgrLoginId) .Select(e => e.OrgNode) .FirstOrDefaultAsync(); if (newOrgNode == null) throw new InvalidOperationException("未找到指定的新管理者"); // 查找新管理者下的最大子节点,生成新的子节点路径 var maxChildNode = await _dbContext.EmployeeDemo .Where(e => e.OrgNode.GetAncestor(1) == newOrgNode) .Select(e => e.OrgNode) .MaxAsync(); var newChildNode = newOrgNode.GetDescendant(maxChildNode, null); // 批量更新旧管理者及其所有子节点的路径 await _dbContext.EmployeeDemo .Where(e => e.OrgNode.IsDescendantOf(oldOrgNode)) .ExecuteUpdateAsync(s => s .SetProperty(e => e.OrgNode, e => e.OrgNode.GetReparentedValue(oldOrgNode, newChildNode))); // 提交事务 await transaction.CommitAsync(); } catch { // 异常时回滚事务 await transaction.RollbackAsync(); throw; } }
关键逻辑说明
- 事务隔离级别:使用
Serializable级别,防止并发修改HierarchyId路径时出现数据不一致,和原存储过程的隔离级别完全匹配。 - HierarchyId操作映射:C#中的
SqlHierarchyId方法与SQL原生方法一一对应:GetAncestor(1):获取父节点GetDescendant:生成指定节点下的新子节点IsDescendantOf:判断节点是否为指定节点的后代(含自身)GetReparentedValue:修改节点的父路径
- 高效批量更新:使用
ExecuteUpdateAsync直接生成SQL批量更新语句,无需加载所有实体到内存,和原存储过程的UPDATE语句效率一致。 - 原子性保障:通过事务的提交/回滚确保整个迁移操作的原子性,要么全部成功,要么全部回滚。
内容的提问来源于stack exchange,提问作者Aktaeon
相关产品推荐
相关产品推荐

