先上一段最近项目中的代码,此代码可以放到自己项目中的dbContext中

public override Task<int> SaveChangesAsync()
{
List<AuditLog> AuditLogs = new List<AuditLog>();
List<DataLensTrackingLog> trackinglogs = new List<DataLensTrackingLog>();
var changeTracker = ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified);
try
{
foreach (var entity in changeTracker)
{
AuditLogs.Clear();
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateElement(TrackingLog.Records));
if (entity.Entity != null)
{
var entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
//string entityName = entity.Entity.GetType().Name;
EntityState state = entity.State;
switch (entity.State)
{
case EntityState.Modified:
//entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
foreach (string prop in entity.OriginalValues.PropertyNames)
{
object currentValue = entity.CurrentValues[prop];
object originalValue = entity.GetDatabaseValues()[prop];//OriginalValues[prop];
if (!Object.Equals(currentValue, originalValue)&&entity.Property(prop).IsModified==true
&&prop.ToLower()!="lastupdateby")
{
AuditLogs.Add(new AuditLog
{
EntityName = entityName,
RecordID = PrimaryKeyValue(entity),
State = state,
ColumnName = prop,
OriginalValue = Convert.ToString(originalValue),
NewValue = Convert.ToString(currentValue),
});
}
}
if (AuditLogs.Count > )
{
TrackingLog.GetXmlForUpdate(doc, AuditLogs);
trackinglogs.Add(new DataLensTrackingLog
{
EntityName = entityName,
Email = this.Email,
XmlDoc = CompressionHelper.Compresse("XmlDoc", new UTF8Encoding().GetBytes(doc.OuterXml)),
CreateTime = DateTime.Now
});
}
break;
case EntityState.Added:
//entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
foreach (string prop in entity.CurrentValues.PropertyNames)
{
AuditLogs.Add(new AuditLog
{
EntityName = entityName,
RecordID = PrimaryKeyValue(entity),
State = state,
ColumnName = prop,
OriginalValue = string.Empty,
NewValue = entity.CurrentValues[prop],
}); }
TrackingLog.GetXmlForUpdate(doc, AuditLogs);
trackinglogs.Add(new DataLensTrackingLog
{
EntityName = entityName,
Email = this.Email,
XmlDoc = CompressionHelper.Compresse("XmlDoc", new UTF8Encoding().GetBytes(doc.OuterXml)),
CreateTime = DateTime.Now
});
break;
case EntityState.Deleted:
//entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
foreach (string prop in entity.OriginalValues.PropertyNames)
{
AuditLogs.Add(new AuditLog
{
EntityName = entityName,
RecordID = PrimaryKeyValue(entity),
State = state,
ColumnName = prop,
OriginalValue = entity.OriginalValues[prop],
NewValue = string.Empty,
}); }
TrackingLog.GetXmlForUpdate(doc, AuditLogs);
trackinglogs.Add(new DataLensTrackingLog
{
EntityName = entityName,
Email = this.Email,
XmlDoc = CompressionHelper.Compresse("XmlDoc", new UTF8Encoding().GetBytes(doc.OuterXml)),
CreateTime = DateTime.Now
});
break;
default:
break;
}
}
}
DataTable dt=TypeConvert.ToDataTable(trackinglogs);
SqlDataHelper.SqlBulkCopy(dt, "DataLensTrackingLog", DataBaseType.ConnLogDataStr);
return base.SaveChangesAsync();
}
catch (Exception ex)
{
throw ex;
}
}

EF6中可以覆写SaveChangesAsync(异步)或者SaveChanges来实现记录变化的跟踪,这其中包括新增、修改、和删除,
dbContext中的属性ChangeTracker可以跟踪属性的变化,即查找实体修改记录:ChangeTracker.Entries().Where(p => p.State ==EntityState.Modified);
查找新增的实体记录行:ChangeTracker.Entries().Where(p => p.State == EntityState.Added);查找删除的实体记录行:
ChangeTracker.Entries().Where(p => p.State == EntityState.Deleted)

获取实体的名字是ObjectContext.GetObjectType(entity.Entity.GetType()).Name,之前获取实体是通过以下方式:
entity.Entity.GetType().Name,但是这种方式会有一个问题,假如说存在以下实体

public partial class DataLensDataPointUniverse
{
[Key]
public int DataPointUniverseId { get; set; }
public int DomicileId { get; set; }
public int ShareClassUniverseId { get; set; }
public int DataPointId { get; set; }
public int CollectionStatusId { get; set; }
public Nullable<System.DateTime> CollectionStartDate { get; set; }
public Nullable<System.DateTime> CollectionEndDate { get; set; }
public int CollectionFrequencyId { get; set; }
public int CollectionPriorityId { get; set; }
public string Restrictions { get; set; }
public int FundFormId { get; set; }
public string InterpretationRules { get; set; }
public string Comments { get; set; }
public string QualityMeasureCompleteness { get; set; }
public string QualityMeasureTimeliness { get; set; }
public string QualityMeasureAccuracy { get; set; }
public int FundCollectionRequirementId { get; set; }
public int LEANProjectId { get; set; }
public Nullable<System.Guid> CreateBy { get; set; }
public Nullable<System.Guid> LastUpdateBy { get; set; }
public Nullable<System.DateTime> CreateDate { get; set; }
public Nullable<System.DateTime> LastUpdateDate { get; set; } public virtual DataLensDataPoint DataLensDataPoint { get; set; }
}

这时候获取的实体名字就可能是类似于这种格式343434343_DataLensDataPoint_3434,为什么会存在这种格式呢,因为该实体中的DataPointId是另个属性 public virtual DataLensDataPoint DataLensDataPoint { get; set; }中的外键,即(即实体DataLensDataPoint中DataPointId)


    
 获取属性当前值entity.CurrentValues[prop](即还未保存到数据库),获取数据库当前值entity.GetDatabaseValues()[prop]
其中的entity.Property(prop).IsModified==true属性是来判断确实该值要存到数据库中,才要去记录日志,因为在Save
之前可能有些实体属性被标记为不做更改entity.Property(prop).IsModified==false;

获取实体主键的值可以用以下方法

private string PrimaryKeyValue(DbEntityEntry entry)
{
var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
if (null == objectStateEntry.EntityKey.EntityKeyValues)
{
return string.Empty;
}
return string.Join(",", objectStateEntry.EntityKey.EntityKeyValues.Select(item => item.Value.ToString()).ToArray());
}

当我们进行数据批量修改的时候我们可以用到EntityFramework.Extended,而不至于一条条的去更新数据库,增添了与数据库的I/O次数,具体的github地址地址为:

https://github.com/loresoft/EntityFramework.Extended,但是同时会有个问题,我们就没法做entitiframework的tracking log的使用,即使用SaveChanges的时候捕捉不到任何变化,如果想使用批量,又能捕捉到变化,可以使用entitiframework来执行sql语句来批量更新,并且也能捕获到数据改变的情况,因为使用了SaveChanges(),参考链接为:/wujingtao/p/5412329.html

Note:EntityFramework.Extended也支持事务.

原文:http://www.jianzhaoyang.com/cby-love/p/5746654.html

EF利用重写SaveChanges()方法实现 审计日志记录的更多相关文章

  1. EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态

    本文目录 查看实体当前.原始和数据库值:DbEntityEntry 查看实体的某个属性值:GetValue<TValue>方法 拷贝DbPropertyValues到实体:ToObject ...

  2. 【数据库】通过触发器实现审计日志记录-demo篇

      触发器实现审计日志记录(记录增.删.改) #创建测试表 CREATE TABLE COMPANY( ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, ...

  3. 利用paramiko的demo_simple.py进行日志记录时遇到的特殊字符

    特殊字符列表: 回车 "\r" "\x13" 响铃 "\x07" 换行 "\n" "\x10" &q ...

  4. ABP理论学习之审计日志

    返回总目录 本篇目录 介绍 配置 通过特性开启/关闭 注意 我项目中的例子 介绍 维基百科说: "审计跟踪(也叫审计日志)是与安全相关的按照时间顺序的记录,记录集或者记录源,它们提供了活动序 ...

  5. ABP官方文档翻译 4.6 审计日志

    审计日志 介绍 关于IAuditingStore 配置 通过特性启用/禁用 注意事项 介绍 维基百科:“审计追踪(也称为审计日志)是与安全相关的按时间先后的记录.记录集合.记录的目的地和源,提供一系列 ...

  6. Kubernetes审计日志方案

    前言 当前Kubernetes(K8S)已经成为事实上的容器编排标准,大家关注的重点也不再是最新发布的功能.稳定性提升等,正如Kubernetes项目创始人和维护者谈到,Kubernetes已经不再是 ...

  7. Abp + MongoDb 改造默认的审计日志存储位置

    一.背景 在实际项目的开发当中,使用 Abp Zero 自带的审计日志功能写入效率比较低.其次审计日志数据量中后期十分庞大,不适合与业务数据存放在一起.所以我们可以重新实现 Abp 的 IAuditi ...

  8. 最全Kubernetes审计日志方案

    前言 当前Kubernetes(K8S)已经成为事实上的容器编排标准,大家关注的重点也不再是最新发布的功能.稳定性提升等,正如Kubernetes项目创始人和维护者谈到,Kubernetes已经不再是 ...

  9. 基于.NetCore3.1系列 —— 日志记录之日志配置揭秘

    一.前言 在项目的开发维护阶段,有时候我们关注的问题不仅仅在于功能的实现,甚至需要关注系统发布上线后遇到的问题能否及时的查找并解决.所以我们需要有一个好的解决方案来及时的定位错误的根源并做出正确及时的 ...

随机推荐

  1. wx小程序自定义组件与页面之间参数传递

    在开发中,很多页面中会使用相同的组件,这时可以将具有相同信息的部分封装成一个组件,方便开发中调用.在调用中可能会涉及到数据的传递问题,例如页面与组件,组件与组件直接的数据传递. 首先看看页面与组件直接 ...

  2. RabbitMQ、Memcached、SQLAlchemy

    一.RabbitMQ 1.基础概念 rabbitMQ说白了就是一个消息队列,类似于Queue,也是生产者与消费者模型.只不过做了扩展,所不同的是Queue在内存中的消息队列,而RabbitMQ是部署在 ...

  3. 新书预告 ArcGIS跨平台开发系列第一本

    新书预告 ArcGIS跨平台开发系列第一本 候选题目: ArcGIS Runtime开发实验实习教程 ArcGIS Runtime开发案例教程 简介: GIS最新现代开发理念打造的跨所有移动和桌面平台 ...

  4. 吴裕雄 20-MySQL NULL 值处理

    MySQL NULL 值处理我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作.为了 ...

  5. vue --轮播图

    轮播图,可以使用mint-ui中的swipe HTML: <Swipe :auto="4000"> <SwipeItem v-for="item in ...

  6. Real Time Rendering 1

    [Real Time Rendering 1] 1.RTR是一本导论.官网:http://www.realtimerendering.com. 2.At around 6 fps, a sense o ...

  7. React DevTools

    [React DevTools] 在应用商店搜索安装.F12可打开.如果是react应用,在最右排会显示react标签. 参考:https://github.com/facebook/react-de ...

  8. 读取excel表格以及生成自动化报告

    数据库读取 标签(空格分隔): 数据库读取 读excel数据xlrd 当登录的账号有多个的时候,我们一般用excel存放测试数据,本节课介绍,python读取excel方法,并保存为字典格式. 1.先 ...

  9. python 内置函数(一),低阶内置函数功能汇总

    python  内置函数  68个 今日主要内容: 1.内置函数 一.内置函数 1.内置函数 详细细节内容地址(id):https://mubu.com/edit/odv-2Dkb6j

  10. 安卓GreenDao框架一些进阶用法整理(转)

    大致分为以下几个方面: 一些查询指令整理 使用SQL语句进行特殊查询 检测表字段是否存在 数据库升级 数据库表字段赋初始值 一.查询指令整理 1.链式执行的指令 return mDaoSession. ...