如何在 asp.net mvc 中创建审计日志/审计跟踪
Posted
技术标签:
【中文标题】如何在 asp.net mvc 中创建审计日志/审计跟踪【英文标题】:How to create audit log / audit trail in asp.net mvc 【发布时间】:2016-09-15 08:55:30 【问题描述】:当我们首先使用代码或实体框架时,有最简单的方法来审计跟踪添加、更新和删除等操作。
【问题讨论】:
查看Audit.EntityFramework 库,为 EntityFramework 的 CRUD 操作生成审计跟踪。 【参考方案1】:创建一个类以在实体添加、修改或删除时捕获更改或跟踪更改。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Web;
namespace MVC_AuditTrail.Models
public class AuditTrailFactory
private DbContext context;
public AuditTrailFactory(DbContext context)
this.context = context;
public Audit GetAudit(DbEntityEntry entry)
Audit audit = new Audit();
// var user = (User)HttpContext.Current.Session[":user"];
audit.UserId = "swapnil";// user.UserName;
audit.TableName = GetTableName(entry);
audit.UpdateDate = DateTime.Now;
audit.TableIdValue = GetKeyValue(entry);
//entry is Added
if (entry.State == EntityState.Added)
var newValues = new StringBuilder();
SetAddedProperties(entry, newValues);
audit.NewData = newValues.ToString();
audit.Actions = AuditActions.I.ToString();
//entry in deleted
else if (entry.State == EntityState.Deleted)
var oldValues = new StringBuilder();
SetDeletedProperties(entry, oldValues);
audit.OldData = oldValues.ToString();
audit.Actions = AuditActions.D.ToString();
//entry is modified
else if (entry.State == EntityState.Modified)
var oldValues = new StringBuilder();
var newValues = new StringBuilder();
SetModifiedProperties(entry, oldValues, newValues);
audit.OldData = oldValues.ToString();
audit.NewData = newValues.ToString();
audit.Actions = AuditActions.U.ToString();
return audit;
private void SetAddedProperties(DbEntityEntry entry, StringBuilder newData)
foreach (var propertyName in entry.CurrentValues.PropertyNames)
var newVal = entry.CurrentValues[propertyName];
if (newVal != null)
newData.AppendFormat("0=1 || ", propertyName, newVal);
if (newData.Length > 0)
newData = newData.Remove(newData.Length - 3, 3);
private void SetDeletedProperties(DbEntityEntry entry, StringBuilder oldData)
DbPropertyValues dbValues = entry.GetDatabaseValues();
foreach (var propertyName in dbValues.PropertyNames)
var oldVal = dbValues[propertyName];
if (oldVal != null)
oldData.AppendFormat("0=1 || ", propertyName, oldVal);
if (oldData.Length > 0)
oldData = oldData.Remove(oldData.Length - 3, 3);
private void SetModifiedProperties(DbEntityEntry entry, StringBuilder oldData, StringBuilder newData)
DbPropertyValues dbValues = entry.GetDatabaseValues();
foreach (var propertyName in entry.OriginalValues.PropertyNames)
var oldVal = dbValues[propertyName];
var newVal = entry.CurrentValues[propertyName];
if (oldVal != null && newVal != null && !Equals(oldVal, newVal))
newData.AppendFormat("0=1 || ", propertyName, newVal);
oldData.AppendFormat("0=1 || ", propertyName, oldVal);
if (oldData.Length > 0)
oldData = oldData.Remove(oldData.Length - 3, 3);
if (newData.Length > 0)
newData = newData.Remove(newData.Length - 3, 3);
public long? GetKeyValue(DbEntityEntry entry)
var objectStateEntry = ((IObjectContextAdapter)context).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
long id = 0;
if (objectStateEntry.EntityKey.EntityKeyValues != null)
id = Convert.ToInt64(objectStateEntry.EntityKey.EntityKeyValues[0].Value);
return id;
private string GetTableName(DbEntityEntry dbEntry)
TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), false).SingleOrDefault() as TableAttribute;
string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name;
return tableName;
public enum AuditActions
I,
U,
D
然后创建审计表实体和上下文类。
并在此方法中覆盖 savechanges 方法,在保存基础实体之前获取审核更改并保存。
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;
namespace MVC_AuditTrail.Models
public class Student
public int StudentID get; set;
public string Name get; set;
public string mobile get; set;
public class Audit
public long Id get; set;
public string TableName get; set;
public string UserId get; set;
public string Actions get; set;
public string OldData get; set;
public string NewData get; set;
public Nullable<long> TableIdValue get; set;
public Nullable<System.DateTime> UpdateDate get; set;
public class StdContext : DbContext
private AuditTrailFactory auditFactory;
private List<Audit> auditList = new List<Audit>();
private List<DbEntityEntry> objectList = new List<DbEntityEntry>();
public StdContext() : base("stdConnection")
Database.SetInitializer<StdContext>(new CreateDatabaseIfNotExists<StdContext>());
public DbSet<Student> Student get; set;
public DbSet<Audit> Audit get; set;
public override int SaveChanges()
auditList.Clear();
objectList.Clear();
auditFactory = new AuditTrailFactory(this);
var entityList = ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified);
foreach (var entity in entityList)
Audit audit = auditFactory.GetAudit(entity);
bool isValid = true;
if (entity.State == EntityState.Modified && string.IsNullOrWhiteSpace(audit.NewData) && string.IsNullOrWhiteSpace(audit.OldData))
isValid = false;
if (isValid)
auditList.Add(audit);
objectList.Add(entity);
var retVal = base.SaveChanges();
if (auditList.Count > 0)
int i = 0;
foreach (var audit in auditList)
if (audit.Actions == AuditActions.I.ToString())
audit.TableIdValue = auditFactory.GetKeyValue(objectList[i]);
this.Audit.Add(audit);
i++;
base.SaveChanges();
return retVal;
【讨论】:
以上是关于如何在 asp.net mvc 中创建审计日志/审计跟踪的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# Asp.net MVC 中创建 websocket 客户端?
我们如何使用 EF 在 ASP.Net MVC 应用程序中创建 3 层架构?
如何在 Visual Studio 2017 的 ASP.NET MVC 中创建自定义生成/脚手架模板(Razor)?
如何在 ASP .net MVC 4 应用程序的 HTML5 中创建带有可点击选项的水平条形图? [关闭]