Files
zszq-trs/YLErpDAL/DataBase/DataChangeTracer.cs
T
2024-05-09 14:06:26 +08:00

278 lines
8.7 KiB
C#

using Microsoft.EntityFrameworkCore.ChangeTracking;
using YLErp;
namespace BaseOUDAL
{
/// <summary>
/// 数据变化追踪
/// </summary>
public class DataChangeTracer
{
List<DataTrace> _list;
List<(DataTrace, EntityEntry)> _listAdded;
readonly DBContextBase _dbcontext;
readonly Dictionary<string, string> _dicNew;
//readonly Dictionary<string, string> _dicOld;
public DataChangeTracer(DBContextBase dbcontext)
{
_dbcontext = dbcontext ?? throw new ArgumentNullException(nameof(dbcontext));
_dicNew = new Dictionary<string, string>();
//_dicOld = new Dictionary<string, string>();
}
/// <summary>
/// 添加数据跟踪
/// </summary>
public DataChangeTracer AddTraces(OptUserInfo optUserInfo)
{
var entityList = _dbcontext.ChangeTracker.Entries()
.Where(p => p.State > EntityState.Unchanged && p.Entity is IDataTrace).ToArray();
if (entityList.Length < 1)
{
return this;
}
if (_list == null)
{
_list = new List<DataTrace>(entityList.Length);
}
foreach (var entityEntry in entityList)
{
var dataTrace = GetDataTrace(entityEntry, optUserInfo);
if (dataTrace == null)
{
continue;
}
_list.Add(dataTrace);
if (dataTrace.TraceFlag == 1 && entityEntry.State == EntityState.Added)
{
if (_listAdded == null)
{
_listAdded = new List<(DataTrace, EntityEntry)>();
}
_listAdded.Add((dataTrace, entityEntry));
}
}
return this;
}
/// <summary>
/// 保存数据跟踪
/// </summary>
public async void SaveTracesAsync()
{
if (_list == null || _list.Count < 1)
{
return;
}
DataTraceDbContext db = null;
try
{
if (_listAdded != null)
{
foreach (var (trace, entry) in _listAdded)
{
trace.DataKeyId = GetKeyValue(entry);
}
}
db = _dbcontext.GetDataTraceDbContext();
db.DataTrace.AddRange(_list);
await db.SaveChangesAsync().ContinueWith(t =>
{
if (t.Exception != null)
{
LogFactory.GetLogger<DataChangeTracer>().Error(t.Exception);
}
});
}
catch (Exception ex)
{
LogFactory.GetLogger<DataChangeTracer>().Error(ex);
}
finally
{
db?.Dispose();
}
}
private DataTrace GetDataTrace(EntityEntry entityEntry, OptUserInfo optUserInfo)
{
if (entityEntry.Entity is IDataTraceIgnore traceIgnore && traceIgnore.IgnoreDataTrace())
{
return null;
}
string dataChanges = GetDataChanges(entityEntry);
var traceFlag = 0;
var keyInfo = string.Empty;
switch (entityEntry.State)
{
case EntityState.Added:
traceFlag = 1;
keyInfo = "新增";
break;
case EntityState.Modified:
traceFlag = 2;
keyInfo = "修改";
if (string.IsNullOrEmpty(dataChanges))
{
return null;
}
break;
case EntityState.Deleted:
traceFlag = 3;
keyInfo = "删除";
break;
}
keyInfo += ((IDataTrace)entityEntry.Entity).GetDataTraceKeyInfo();
var keyId = string.Empty;
if (entityEntry.Entity is IDataTraceV2 dataTraceV2)
{
keyId = dataTraceV2.GetDataTraceKeyId() ?? string.Empty;
traceFlag = string.IsNullOrEmpty(keyId) || keyId == "0" ? 1 : traceFlag + 100;
}
else if (entityEntry.State != EntityState.Added)
{
keyId = GetKeyValue(entityEntry);
}
var user = optUserInfo ?? OptUserInfo.SystemUser;
var entityType = entityEntry.Entity.GetType();
var tableName = entityType.Name;
if (entityEntry.Entity is IDataTraceV3 traceV3)
{
var tableName2 = traceV3.GetDataTraceTableName();
if (!string.IsNullOrEmpty(tableName2))
{
tableName = tableName2;
}
}
return new DataTrace
{
TableName = tableName,
DataState = entityEntry.State.ToString(),
CreateTime = DateTime.Now,
DataKeyId = keyId,
DataKeyInfo = keyInfo,
OptId = user.UserId,
OptName = user.UserName,
IpAddress = user.IpAddress,
DataChanges = dataChanges,
//OldValues = oldValues,
TraceFlag = traceFlag
};
}
private static string GetKeyValue(EntityEntry entry)
{
var keyProps = entry.Metadata.FindPrimaryKey().Properties;
if (keyProps == null || keyProps.Count < 1)
{
return string.Empty;
}
if (keyProps.Count > 0 && "id".Equals(keyProps[0].Name, StringComparison.OrdinalIgnoreCase))
{
return entry.Property(keyProps[0].Name).CurrentValue?.ToString();
}
return keyProps.ToDictionary(n => n.Name, m => entry.Property(m.Name).CurrentValue?.ToString()).ToJson();
}
private string GetDataChanges(EntityEntry entry)
{
PropertyValues dbValues = null;
if (entry.State != EntityState.Added)
{
dbValues = entry.GetDatabaseValues();
//等于null说明这个实体对象在数据库中无值但在实体上下文中做了变更(比如事务或附加)
if (dbValues?.Properties == null || !dbValues.Properties.Any())
{
return string.Empty;
}
}
var dic = new Dictionary<string, string>();
var properties = dbValues?.Properties ?? entry.CurrentValues.Properties;
foreach (var prop in properties)
{
if (ExclueNames.Contains(prop.Name))
{
continue;
}
switch (entry.State)
{
case EntityState.Added:
{
var newVal = entry.CurrentValues[prop];
if (newVal != null)
{
dic[prop.Name] = Convert.ToString(newVal);
}
}
break;
case EntityState.Deleted:
{
var oldVal = dbValues[prop];
if (oldVal != null)
{
dic[prop.Name] = Convert.ToString(oldVal);
}
}
break;
case EntityState.Modified:
{
var oldVal = dbValues[prop];
var newVal = entry.CurrentValues[prop];
var newValStr = Convert.ToString(newVal);
var oldValStr = Convert.ToString(oldVal);
if (!Equals(newValStr, oldValStr))
{
dic[prop.Name] = newValStr;
}
}
break;
}
}
return dic.Count > 0 ? dic.ToJson() : string.Empty;
}
readonly static IEnumerable<string> ExclueNames = new string[]
{
nameof(DBModelWithOperator.id),
nameof(DBModelWithOperator.OptId),
nameof(DBModelWithOperator.OptName),
nameof(DBModelWithOperator.OptDate),
nameof(SystemUser.UserToken),
};
}
}