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

如何修改Auditable类实现不同表审计字段的动态带前缀列名

适配不同表前缀的审计字段解决方案

针对不同表需要带专属前缀的审计字段需求,我们可以通过自定义特性+反射赋值的方式替换原有的固定字段基类方案,具体实现如下:

1. 定义审计字段标记特性

首先创建特性类,用来标记实体属性对应的审计类型:

[AttributeUsage(AttributeTargets.Property)]
public class AuditFieldAttribute : Attribute
{
    public AuditFieldType FieldType { get; }

    public AuditFieldAttribute(AuditFieldType fieldType)
    {
        FieldType = fieldType;
    }
}

public enum AuditFieldType
{
    CreatedBy,
    CreatedDate,
    ModifiedBy,
    ModifiedDate
}

2. 实体类定义带前缀的审计字段

每个表的实体类自行定义带专属前缀的审计字段,并通过AuditField特性标记对应的审计类型:

// TN1表实体示例
public class TN1Entity
{
    // 业务字段...

    [AuditField(AuditFieldType.CreatedBy)]
    public decimal? TN1_CreatedBy { get; set; }

    [AuditField(AuditFieldType.CreatedDate)]
    public DateTime? TN1_CreatedDate { get; set; }

    [AuditField(AuditFieldType.ModifiedBy)]
    public decimal? TN1_ModifiedBy { get; set; }

    [AuditField(AuditFieldType.ModifiedDate)]
    public DateTime? TN1_ModifiedDate { get; set; }
}

// TN2表实体示例
public class TN2Entity
{
    // 业务字段...

    [AuditField(AuditFieldType.CreatedBy)]
    public decimal? TN2_CreatedBy { get; set; }

    [AuditField(AuditFieldType.CreatedDate)]
    public DateTime? TN2_CreatedDate { get; set; }

    [AuditField(AuditFieldType.ModifiedBy)]
    public decimal? TN2_ModifiedBy { get; set; }

    [AuditField(AuditFieldType.ModifiedDate)]
    public DateTime? TN2_ModifiedDate { get; set; }
}

3. 修改SaveChanges方法实现自动赋值

重写SaveChanges时,遍历所有实体条目,通过反射识别带AuditField特性的属性,根据实体状态和审计类型自动赋值:

public override int SaveChanges()
{
    decimal? loggedinUserId = null;
    if (_httpContext.Items["USER"] != null)
    {
        var userInfo = _httpContext.Items["USER"];
        var idProp = userInfo.GetType().GetProperty("Id");
        if (idProp != null)
        {
            loggedinUserId = (decimal?)idProp.GetValue(userInfo);
        }
    }

    foreach (var entry in ChangeTracker.Entries())
    {
        if (entry.State != EntityState.Added && entry.State != EntityState.Modified)
            continue;

        var auditProperties = entry.Entity.GetType()
            .GetProperties()
            .Where(p => p.GetCustomAttribute<AuditFieldAttribute>() != null);

        foreach (var prop in auditProperties)
        {
            var auditAttr = prop.GetCustomAttribute<AuditFieldAttribute>();
            if (auditAttr == null) continue;

            switch (auditAttr.FieldType)
            {
                case AuditFieldType.CreatedBy:
                    if (entry.State == EntityState.Added && loggedinUserId.HasValue)
                        prop.SetValue(entry.Entity, loggedinUserId);
                    break;
                case AuditFieldType.CreatedDate:
                    if (entry.State == EntityState.Added)
                        prop.SetValue(entry.Entity, DateTime.Now);
                    break;
                case AuditFieldType.ModifiedBy:
                    if (entry.State == EntityState.Modified && loggedinUserId.HasValue)
                        prop.SetValue(entry.Entity, loggedinUserId);
                    break;
                case AuditFieldType.ModifiedDate:
                    if (entry.State == EntityState.Modified)
                        prop.SetValue(entry.Entity, DateTime.Now);
                    break;
            }
        }
    }

    return base.SaveChanges();
}

方案优势

  • 完全适配不同表的前缀需求,实体字段命名灵活,不受基类固定字段限制
  • 审计逻辑与实体字段解耦,新增实体时只需添加带特性的字段,无需修改保存逻辑
  • 反射逻辑简洁高效,仅针对有审计标记的属性处理,性能影响可忽略

内容的提问来源于stack exchange,提问作者smilu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:57:44