1.首先是建審計存儲表 並建立實體 2.EF工作單元類的實現(百度有很多實現方式) 這裡的AuthUserModel是當前用戶類 3.採用Autofac.Extras.DynamicProxy實現AOP 不知道Autofac.Extras.DynamicProxy能不能直接作用在方法上? 使用Aud ...
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.測試
審計日誌增加成功