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

使用SqlTableDependency做表变更日志时如何正确获取提交变更的操作用户

问题核心原因
  • 你的ITableChangeBroadcastService实现类TestData大概率注册为了全局单例,整个应用生命周期仅会初始化一次,构造函数中存储的adUserName永远是第一次触发服务初始化的用户身份,多用户场景下自然不会更新。
  • SqlTableDependency的OnChanged事件由数据库变更触发,运行在独立的后台线程中,和用户的请求上下文完全隔离,此时访问IHttpContextAccessor拿到的必然是null,无法通过该方式获取操作人。
  • 该事件的签名由SqlTableDependency框架定义,你无法直接向事件处理方法传入自定义的额外参数。
最优解决方案

通过给业务表增加操作人字段的方式实现身份传递,完全绕开上下文获取的问题,同时兼容非本系统发起的数据库变更场景:

  1. 给Origin实体和对应的数据库表增加LastModifiedAdUser字段,用于存储最后一次操作这条记录的用户身份。
  2. 在用户主动发起数据变更的UpdateDataAsync方法中,将前端传入的当前操作人用户名赋值给该字段,同步写入数据库。
  3. SqlTableDependency触发变更事件时,直接从返回的最新实体中读取LastModifiedAdUser字段写入变更日志即可。
代码修改示例

1. 扩展Origin实体

public class Origin
{
    // 原有字段保持不变
    public int OrigId { get; set; }
    public string OriginCode { get; set; }
    public string OriginDesc { get; set; }
    public bool Inactive { get; set; }
    public string StateCode { get; set; }
    public string CountryCode { get; set; }

    // 新增操作人字段
    public string LastModifiedAdUser { get; set; }
}

别忘了同步给数据库的Origin表添加同名varchar类型字段。

2. 修改UpdateDataAsync方法

public async Task UpdateDataAsync(Origin origin, string adUserName)
{
    // 更新前先赋值操作人到实体,写入数据库
    origin.LastModifiedAdUser = adUserName;
    using (var conn = new SqlConnection(_connectionString.Value))
    {
        await conn.UpdateAsync(origin);
    }
}

3. 清理TestData类的无效逻辑

public class TestData : ITableChangeBroadcastService, IDisposable
{
    private const string TableName = "Origin";
    private SqlTableDependency<Origin> _notifier;
    private ConnectionString _connectionString;
    public event TestDataChangeDelegate OnOriginChanged;
    // 删掉IHttpContextAccessor注入和adUserName存储字段,已经不需要了
    private int lastLoggedId;

    public TestData(ConnectionString connectionString)
    {
        _connectionString = connectionString;
        _notifier = new SqlTableDependency<Origin>(_connectionString.Value, TableName, includeOldValues:true);
        _notifier.OnChanged += this.TableDependency_Changed;
        _notifier.Start();
    }

    private async void TableDependency_Changed(object sender, RecordChangedEventArgs<Origin> e)
    {
        if (this.OnOriginChanged != null)
        {
            this.OnOriginChanged(this, new TestDataChangeEventArgs(e.Entity, e.EntityOldValues));
            using (var conn = new SqlConnection(_connectionString.Value))
            {
                // 直接从最新实体中取操作人字段,非本系统变更可以设置默认值
                var operatorUser = e.Entity.LastModifiedAdUser ?? "系统操作";
                lastLoggedId = await conn.LogChangeAsync(e.Entity, e.EntityOldValues, operatorUser).ConfigureAwait(false);
            }
        }
    }

    // 其他原有方法保持不变
}
补充说明

如果后续需要在自定义的OnOriginChanged事件中传递更多参数,直接修改TestDataChangeEventArgs类增加对应属性即可,触发事件时赋值就能在订阅端拿到。

内容的提问来源于stack exchange,提问作者jon.r

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:36:05