如何获取实体/表的名称和添加审计的记录号?
Posted
技术标签:
【中文标题】如何获取实体/表的名称和添加审计的记录号?【英文标题】:How do I get the name of the entity/table and the record number for adding audit? 【发布时间】:2019-06-10 22:16:53 【问题描述】:我正在尝试使用 EF DbContext 为我的系统执行审核方法。我覆盖了 SaveChanges 事件。但是,我有两个困难需要帮助。我在互联网上和 *** 上阅读了很多内容,但我仍然无法找到解决方案。你能帮帮我吗?
1) 添加记录时,我无法获取表的实际名称。当我将记录添加到表中时,名称只是“对象”。其他操作同名正常。
2) 进入注册表后,我希望将注册表 ID 放入审核日志。有什么建议吗?
如果问题的答案如此明显,但我真的不明白如何继续,我期待道歉。
public partial class coletasEntities : DbContext
public override int SaveChanges()
ChangeTracker.DetectChanges();
foreach (var change in ChangeTracker.Entries())
if (change is auditoria || change.State == EntityState.Detached || change.State == EntityState.Unchanged)
continue;
//Pega o nome da tabela
var entityName = change.Entity.GetType().Name;
//var entityName2 = change.Entity.GetType().BaseType()
if (entityName == "auditoria") continue;
// Get the Table() attribute, if one exists
//TableAttribute tableAttr = change.Entity.GetType().BaseType.Name;
TableAttribute tableAttr = change.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), false).SingleOrDefault() as TableAttribute;
// Get table name (if it has a Table attribute, use that, otherwise get the pluralized name)
//string tableName = tableAttr != null ? tableAttr.Name : ((TableAttribute)tableAttr[0]).Name;
//string tableName = tableAttr != null ? tableAttr.Name : change.Entity.GetType().Name;
string tableName = tableAttr != null ? tableAttr.Name : change.Entity.GetType().BaseType.Name;
// Get primary key value (If you have more than one key column, this will need to be adjusted)
//string keyName = change.Entity.GetType().GetProperties().Single(p => p.GetCustomAttributes(typeof(KeyAttribute), false).Count() > 0).Name;
if (change.State == EntityState.Added)
using (coletasEntities ctx = new coletasEntities())
foreach (var prop in change.CurrentValues.PropertyNames)
auditoria audit = new auditoria();
audit.campo = prop.ToString();
audit.data = DateTime.Now.Date;
audit.hora = DateTime.Now.ToShortTimeString();
audit.id_registro = 0;
audit.id_usuario = Global.id_usuario;
audit.tabela = tableName;
audit.tipo_operacao = (int)change.State;
audit.valor_antigo = "";
try
audit.valor_novo = change.CurrentValues[prop].ToString();
catch
audit.valor_novo = "";
ctx.auditoria.Add(audit);
ctx.SaveChanges();
continue;
else if (change.State == EntityState.Deleted)
using (coletasEntities ctx = new coletasEntities())
foreach (var prop in change.OriginalValues.PropertyNames)
auditoria audit = new auditoria();
audit.campo = prop.ToString();
audit.data = DateTime.Now.Date;
audit.hora = DateTime.Now.ToShortTimeString();
audit.id_registro = 0;
audit.id_usuario = Global.id_usuario;
audit.tabela = tableName;
audit.tipo_operacao = (int)change.State;
try
audit.valor_antigo = change.OriginalValues[prop].ToString();
catch
audit.valor_antigo = "";
audit.valor_novo = "";
ctx.auditoria.Add(audit);
ctx.SaveChanges();
continue;
else if (change.State == EntityState.Modified)
using (coletasEntities ctx = new coletasEntities())
foreach (var prop in change.OriginalValues.PropertyNames)
auditoria audit = new auditoria();
audit.campo = prop.ToString();
audit.data = DateTime.Now.Date;
audit.hora = DateTime.Now.ToShortTimeString();
audit.id_registro = 0;
audit.id_usuario = Global.id_usuario;
audit.tabela = tableName;
audit.tipo_operacao = (int)change.State;
try
audit.valor_antigo = change.OriginalValues[prop].ToString();
catch
audit.valor_antigo = "";
try
audit.valor_novo = change.CurrentValues[prop].ToString();
catch
audit.valor_novo = "";
if (audit.valor_antigo != audit.valor_novo)
ctx.auditoria.Add(audit);
ctx.SaveChanges();
continue;
else
// Otherwise, don't do anything, we don't care about Unchanged or Detached entities
return base.SaveChanges();
有什么建议吗?
【问题讨论】:
string tableName = tableAttr != null ? tableAttr.Name : change.Entity.GetType().BaseType.Name;
您记录的是 BaseType 的名称,而不是实体类型
& 我无法理解您的第二个问题以及它在您的代码中适用的上下文。我建议研究如何创建 MCV 示例。
关于我的第二个问题:插入新记录后,我想用新生成的 ID 号对其进行审核。
【参考方案1】:
使用这个 auditEntry.TableName = entry.Metadata.Relational().TableName; 下面是一个例子:
foreach (var entry in ChangeTracker.Entries())
if (entry.Entity is Audit || entry.State == EntityState.Detached ||
entry.State == EntityState.Unchanged)
continue;
var auditEntry = new AuditEntry(entry);
auditEntry.TableName = entry.Metadata.Relational().TableName;
auditEntries.Add(auditEntry);
foreach (var property in entry.Properties)
if (property.IsTemporary)
auditEntry.TemporaryProperties.Add(property);
continue;
string propertyName = property.Metadata.Name;
if (property.Metadata.IsPrimaryKey())
auditEntry.KeyValues[propertyName] = property.CurrentValue;
continue;
switch (entry.State)
case EntityState.Added:
auditEntry.NewValues[propertyName] = property.CurrentValue;
break;
case EntityState.Deleted:
auditEntry.OldValues[propertyName] = property.OriginalValue;
break;
case EntityState.Modified:
if (property.IsModified)
auditEntry.OldValues[propertyName] = property.OriginalValue;
auditEntry.NewValues[propertyName] = property.CurrentValue;
break;
public class AuditEntry
public AuditEntry()
Changes = new List<AuditDelta>();
public AuditEntry(EntityEntry entry)
Entry = entry;
Changes = new List<AuditDelta>();
public string CreateUser get; set;
public string ActionMessage get; set;
public string ActionType get; set;
public EntityEntry Entry get;
public string TableName get; set;
public int ModuleType get; set;
public Dictionary<string, object> KeyValues get; = new Dictionary<string, object>();
public Dictionary<string, object> ForeignKeyValues get; = new Dictionary<string, object>();
public Dictionary<string, object> OldValues get; = new Dictionary<string, object>();
public Dictionary<string, object> NewValues get; = new Dictionary<string, object>();
public Dictionary<string, object> EnitityNameLabels get; = new Dictionary<string, object>();
public List<PropertyEntry> TemporaryProperties get; = new List<PropertyEntry>();
public bool HasTemporaryProperties => TemporaryProperties.Any();
public List<AuditDelta> Changes get; set;
public string DateTimeStamp get; set;
public AuditTrail ToAudit()
var audit = new AuditTrail();
audit.tablename = TableName;
audit.actiontype = ActionType;
audit.CreateUser = CreateUser;
audit.moduletype = ModuleType;
audit.actionmessage = ActionMessage;
audit.CreateDate = DateTime.UtcNow;
audit.primarykeyvalues = JsonConvert.SerializeObject(KeyValues);
audit.foreignkeyvalues = ForeignKeyValues.Count == 0 ? null : JsonConvert.SerializeObject(ForeignKeyValues);
audit.oldvalues = OldValues.Count == 0 ? null : JsonConvert.SerializeObject(OldValues);
audit.newvalues = NewValues.Count == 0 ? null : JsonConvert.SerializeObject(NewValues);
audit.enititynamelabels = EnitityNameLabels.Count == 0 ? null : JsonConvert.SerializeObject(EnitityNameLabels);
audit.changes = Changes.Count == 0 ? null : JsonConvert.SerializeObject(Changes);
return audit;
public class AuditDelta
public string FieldName get; set;
public string ValueBefore get; set;
public string ValueAfter get; set;
public int FieldId get; set;
【讨论】:
这是哪里来的 frmo ? entry.Metadata.Relational().TableName 它来自 Microsoft.EntityFrameworkCore.ChangeTracking 类。以上是关于如何获取实体/表的名称和添加审计的记录号?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 mysql 表中获取自动递增字段名称或主键字段名称?