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

如何将类属性值存储至另一数据库表并标记需双存储属性?

几种实现类属性跨表同步的方案

嘿,你的需求我懂——就是想让Audited类里的部分属性既留在自身表,又同步到Summary这类别的领域对象表对吧?我给你分享几个实际项目里常用的实现方式,你可以根据自己的技术栈选:

方案1:自定义特性标记需要同步的属性

这是最直观的方式,通过自定义一个特性来标记哪些属性需要双写,然后在持久化的时候通过反射读取这些属性的值,同步到Summary对象。

首先定义一个自定义特性:

[AttributeUsage(AttributeTargets.Property)]
public class SyncToSummaryAttribute : Attribute
{
    // 可以加配置参数,指定对应Summary里的属性名
    public string TargetPropertyName { get; set; }

    public SyncToSummaryAttribute(string targetPropertyName = null)
    {
        TargetPropertyName = targetPropertyName;
    }
}

然后给你的Audited类属性加上这个标记:

public class Audited { 
    public virtual int Id{ get; set; } 

    [SyncToSummary("AuditedFieldName")] // 指定Summary里对应的属性名
    public virtual string FieldName{ get; set; } 

    [SyncToSummary] // 如果属性名一致,可省略参数
    public virtual string FieldValue{ get; set; } 
}

接下来在数据持久化逻辑里(比如Repository的Save方法)处理同步:

public void SaveAudited(Audited audited)
{
    // 先保存Audited到自身表
    _auditedRepository.Save(audited);

    // 生成对应的Summary对象
    var summary = new Summary();
    
    // 反射获取所有带SyncToSummaryAttribute的属性
    var properties = typeof(Audited).GetProperties()
        .Where(p => Attribute.IsDefined(p, typeof(SyncToSummaryAttribute)));

    foreach (var prop in properties)
    {
        var attr = prop.GetCustomAttribute<SyncToSummaryAttribute>();
        // 获取目标属性名,默认和原属性名一致
        var targetPropName = string.IsNullOrEmpty(attr.TargetPropertyName) 
            ? prop.Name 
            : attr.TargetPropertyName;
        
        var targetProp = typeof(Summary).GetProperty(targetPropName);
        if (targetProp != null)
        {
            // 复制属性值
            targetProp.SetValue(summary, prop.GetValue(audited));
        }
    }

    // 保存Summary到对应表
    _summaryRepository.Save(summary);
}

方案2:用映射工具简化赋值(比如AutoMapper)

如果你的项目已经在用AutoMapper这类映射工具,直接配置映射规则会更简洁,不用手写反射逻辑。

先配置Audited到Summary的映射:

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Audited, Summary>()
            .ForMember(dest => dest.AuditedFieldName, opt => opt.MapFrom(src => src.FieldName))
            .ForMember(dest => dest.FieldValue, opt => opt.MapFrom(src => src.FieldValue))
            // 其他不需要同步的属性可以忽略
            .ForMember(dest => dest.Id, opt => opt.Ignore());
    }
}

然后在保存的时候直接映射:

public void SaveAudited(Audited audited)
{
    _auditedRepository.Save(audited);
    var summary = _mapper.Map<Summary>(audited);
    // 补充Summary的其他必要属性
    summary.CreatedTime = DateTime.Now;
    _summaryRepository.Save(summary);
}

方案3:领域层封装同步逻辑

如果想把同步逻辑内聚在领域对象里,让业务逻辑更清晰,可以给Audited类加一个生成Summary的方法:

public class Audited { 
    public virtual int Id{ get; set; } 
    public virtual string FieldName{ get; set; } 
    public virtual string FieldValue{ get; set; } 

    // 生成对应的Summary对象
    public Summary GenerateSummary()
    {
        return new Summary
        {
            AuditedFieldName = this.FieldName,
            FieldValue = this.FieldValue,
            AuditedId = this.Id // 关联原Audited的ID
        };
    }
}

然后在业务层调用:

public void ProcessAudited(Audited audited)
{
    _auditedRepository.Save(audited);
    var summary = audited.GenerateSummary();
    _summaryRepository.Save(summary);
}

这几种方案各有优劣:

  • 自定义特性适合需要灵活配置的场景,后期改同步属性只需要加标记就行
  • AutoMapper适合已有映射工具的项目,减少重复代码
  • 领域层封装适合强调领域逻辑内聚的DDD项目,让对象自己负责生成关联对象

你可以根据自己项目的实际情况选~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:35:20