You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 09:07:31