如何获取实体/表的名称和添加审计的记录号?

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 类。

以上是关于如何获取实体/表的名称和添加审计的记录号?的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有连接表的情况下获取多条记录[关闭]

java中,如何通过实体类名称获取对应的数据表名称

如何从 mysql 表中获取自动递增字段名称或主键字段名称?

如何在codeigniter中获取mysql表的字段名?

如何使用实体框架和 MySQL 获取每个组的最新记录,包括相关实体

如何使用普通 JDBC 获取目标表的名称和外键列的列