net core API 后台系统操作日志的实现思路
系统操作日志的实现思路主要问题不在于写日志和表结构设计上。
主要问题在识别出哪些数据做了修改。并生成日志。
表中数据列众多,且要监控多个表。如果要监控的每个表都去写代码去监控和转换这样的工作量就会比较大。
如,用户表【Name,sex,Age】
生成的操作日志是:XX人在XX时间修改了用户的【姓名】修改前:xxx,修改后:xxx,【性别】修改前:XXXX,修改后。操作结果:成功。
我的思路是使用反射,写个通用的比较方法将修改前对象和修改后对象转入,使用反射去比较两个对像的值是否修改,如果修改了将字段的描述名称取出来生成日志。
下面是代码:
/// <summary>
/// 用户表 实体
/// </summary>
[MfTable("TB_User")]
public class TB_UserModel : BaseModel
{
/// <summary>
///
/// </summary>
[MfKey]
[Description("主键")]
public string F_Id { get; set; }/// <summary>
/// 真实姓名
/// </summary>
[Description("真实姓名")]
public string F_RealName { get; set; }
/// <summary>
/// 性别
/// </summary>
[Description("性别")]
public int F_Sex { get; set; }
/// <summary>
/// 手机号
/// </summary>
[Description("手机号")]
public string F_Phone { get; set; }
}
Model比较帮助类
ModelComparisonHelper
/// <summary>
/// Model比较帮助类
/// </summary>
public static class ModelComparisonHelper
{
/// <summary>
/// 类的属性集合 key:类名,val:属性集合
/// </summary>
private static readonly ConcurrentDictionary<string, Dictionary<string, PropertyInfo>> PropertieList = new ConcurrentDictionary<string, Dictionary<string, PropertyInfo>>();
/// <summary>
/// 属性特性集合 key:类名.属性名,val:属性特性集合
/// </summary>
private static readonly ConcurrentDictionary<string, Dictionary<string, string>> DescriptionList = new ConcurrentDictionary<string, Dictionary<string, string>>();
private static object lockObj = new object();
/// <summary>
/// 实体比对方法
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <param name="originalModel">修改前实体</param>
/// <param name="updatedModel">修改后实体</param>
/// <returns>返回两个实体的差异值集合</returns>
public static List<ModelComparisonResult> Comparison<TModel>(TModel originalModel, TModel updatedModel)
{
var resultList = new List<ModelComparisonResult>();
if (originalModel != null && updatedModel != null)
{
var type = originalModel.GetType();
var typeName = type.Name;
if (!PropertieList.ContainsKey(typeName))
{
lock (lockObj)
{
if (!PropertieList.ContainsKey(typeName))
{
var properties = type.GetProperties().ToDictionary(t => t.Name);
PropertieList.TryAdd(typeName, properties);
var descriptions = new Dictionary<string, string>(properties.Count);
foreach (var key in properties.Keys)
{
PropertyInfo propertie = properties[key];
var descriptionAttribute = propertie.GetCustomAttribute(typeof(DescriptionAttribute));
if (descriptionAttribute != null)
{
if (!descriptions.ContainsKey(key))
{
descriptions.Add(key, (descriptionAttribute as DescriptionAttribute).Description);
}
}
}
DescriptionList.TryAdd(typeName, descriptions);
}
}
}
//开始比对
if (PropertieList.ContainsKey(typeName))
{
Dictionary<string, PropertyInfo> propertieList = null;
PropertieList.TryGetValue(typeName, out propertieList);
Dictionary<string, string> descriptionList = null;
DescriptionList.TryGetValue(typeName, out descriptionList);
if (propertieList != null && descriptionList != null)
{
foreach (var key in propertieList.Keys)
{
PropertyInfo propertie = propertieList[key];
var originalModelVal = propertie.GetValue(originalModel).ToString();
var updatedModelVal = propertie.GetValue(updatedModel).ToString();
if (!originalModelVal.Equals(updatedModelVal))
{
var description = string.Empty;
if (descriptionList.ContainsKey(key))
{
description = descriptionList[key];
}
resultList.Add(new ModelComparisonResult()
{
ColumnName = key,
ColumnNameDescription = description,//获取实体属性的描述信息,Description的值
OriginalVal = originalModelVal,
UpdatedVal = updatedModelVal,
Description = string.Format("更新[{0}]修改前为[{1}],修改后为[{2}]", description, originalModelVal, updatedModelVal),
});
}
}
}
}
}
return resultList;
}
}
/// <summary>
/// 实体比对结果类
/// </summary>
public class ModelComparisonResult
{
/// <summary>
/// 列名
/// </summary>
public string ColumnName { get; set; }
/// <summary>
/// 列名的Description 属性值
/// </summary>
public string ColumnNameDescription { get; set; }
/// <summary>
/// 修改前的值
/// </summary>
public string OriginalVal { get; set; }
/// <summary>
/// 修改后的值
/// </summary>
public string UpdatedVal { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
}
调用
var resultList = ModelComparisonHelper.Comparison(o_model, model);
从resultList 集合中可以获取比对结果,下面怎么 处理就看实际需求了。