1.首先是建审计存储表
CREATE TABLE [dbo].[Audit] ( [Id] [uniqueidentifier] NOT NULL, [EntityName] [nvarchar](100), [OldValue] [nvarchar](max), [NewValue] [nvarchar](max), [StateName] [nvarchar](255), [CreatedBy] [nvarchar](255), [CreatedDate] [datetime] NOT NULL, CONSTRAINT [PK_dbo.Audit] PRIMARY KEY ([Id]) ) Go
并建立实体
/// <summary> /// AuditEntity /// </summary> public class AuditEntity : Entity { public AuditEntity() { this.EntityName = string.Empty; this.OldValue = string.Empty; this.NewValue = string.Empty; this.StateName = string.Empty; this.CreatedBy = string.Empty; this.CreatedDate = DateTime.Now; } public string EntityName { get; set; } /// <summary> /// /// </summary> public string OldValue { get; set; } /// <summary> /// /// </summary> public string NewValue { get; set; } /// <summary> /// /// </summary> public string StateName { get; set; } /// <summary> /// /// </summary> public string CreatedBy { get; set; } /// <summary> /// /// </summary> public DateTime CreatedDate { get; set; } }
2.EF工作单元类的实现(百度有很多实现方式)
/// <summary> /// 工作单元接口 /// </summary> public partial interface IUnitOfWork { bool Commit(); }
/// <summary> /// 工作单元实现类 /// </summary> public partial class UnitOfWork : IUnitOfWork, IDisposable { #region 数据上下文 /// <summary> /// 数据上下文 /// </summary> private BaseDbContext _context; private AuthUserModel _user; public UnitOfWork(BaseDbContext context, AuthUserModel user) { _context = context; _user = user; } #endregion public virtual bool Commit() { return _context.SaveChanges() > 0; } public void Dispose() { if (_context != null) { _context.Dispose(); } GC.SuppressFinalize(this); } }
这里的AuthUserModel是当前用户类
public class AuthUserModel { public string UserName { get; set; } public string UserId { get; set; } public string Role { get; set; } }
3.采用Autofac.Extras.DynamicProxy实现AOP
不知道Autofac.Extras.DynamicProxy能不能直接作用在方法上?
public class AuditLog : IInterceptor { private AuthUserModel _user; private BaseDBContext _context; public AuditLog(AuthUserModel user, BaseDBContext context ) { _user = user; _context = context; } public void Intercept(IInvocation invocation) { var a = _user; string name = invocation.Method.Name; if (name== "Commit") { try { var list = new List<AuditEntity>(); var b = invocation.InvocationTarget as BaseUnitOfWork; b.context.ChangeTracker.DetectChanges(); var changes = b.context.ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted); foreach (var change in changes) { var temp = new AuditEntity() { CreatedBy = _user.UserName }; //实体名称 temp.EntityName = change.Entity.GetType().Name; // Entity Added if (change.State == EntityState.Added) { temp.NewValue = JsonConvert.SerializeObject(change.Entity); temp.StateName = "Added"; list.Add(temp); } // Entity Deleted else if (change.State == EntityState.Deleted) { temp.OldValue = JsonConvert.SerializeObject(change.Entity); temp.StateName = "Deleted"; list.Add(temp); } // Entity Modified else if (change.State == EntityState.Modified) { //string newStr= "{ " ; string oldStr = "{ "; foreach (var propertyEntry in change.Metadata.GetProperties()) { //if (change.Property(prop.Name).IsModified) //{ var PropertyName = propertyEntry.Name; var currentValue = change.Property(propertyEntry.Name).CurrentValue; var originalValue = change.Property(propertyEntry.Name).OriginalValue; //newStr = newStr + """ + PropertyName + """ + ":" + """ + currentValue + """ + ","; oldStr = oldStr + """ + PropertyName + """ + ":" + """ + originalValue + """ + ","; //} } oldStr = oldStr.Remove(oldStr.Length - 1, 1); oldStr = oldStr + "}"; //newStr = newStr.Remove(oldStr.Length - 1, 1); //newStr = newStr + "}"; temp.OldValue = oldStr; temp.NewValue = JsonConvert.SerializeObject(change.Entity); temp.StateName = "Modified"; list.Add(temp); } } invocation.Proceed(); //将list写入表 //。。。。 } catch (Exception ex) { throw; } finally { } } else { invocation.Proceed(); } } public IEnumerable<KeyValuePair<string, object>> MapParameters(object[] arguments, ParameterInfo[] getParameters) { for (int i = 0; i < arguments.Length; i++) { yield return new KeyValuePair<string, object>(getParameters[i].Name, arguments[i]); } } }
使用AuditLog
builder.RegisterType<AuditLog>(); builder.RegisterType<UnitOfWork>() .As<IUnitOfWork>().EnableInterfaceInterceptors().InterceptedBy(typeof(AuditLog));
4.调用代码
public class UserManagerApp { private IUnitOfWork _uow; public UserManagerApp( IUnitOfWork uow) { _uow = uow; } public void Delete(Guid[] ids) { //delete 方法 //.......... //提交事务 _uow.Commit(); } }
[HttpDelete] [Authorize] public Response Delete(Guid[] ids) { var result = new Response(); try { _app.Delete(ids); } catch (Exception ex) { result.Status = false; result.Message = ex.Message; } return result; }
5.测试
审计日志增加成功