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

  1. public override Task<int> SaveChangesAsync()
  2. {
  3. List<AuditLog> AuditLogs = new List<AuditLog>();
  4. List<DataLensTrackingLog> trackinglogs = new List<DataLensTrackingLog>();
  5. var changeTracker = ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified);
  6. try
  7. {
  8. foreach (var entity in changeTracker)
  9. {
  10. AuditLogs.Clear();
  11. XmlDocument doc = new XmlDocument();
  12. doc.AppendChild(doc.CreateElement(TrackingLog.Records));
  13. if (entity.Entity != null)
  14. {
  15. var entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
  16. //string entityName = entity.Entity.GetType().Name;
  17. EntityState state = entity.State;
  18. switch (entity.State)
  19. {
  20. case EntityState.Modified:
  21. //entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
  22. foreach (string prop in entity.OriginalValues.PropertyNames)
  23. {
  24. object currentValue = entity.CurrentValues[prop];
  25. object originalValue = entity.GetDatabaseValues()[prop];//OriginalValues[prop];
  26. if (!Object.Equals(currentValue, originalValue)&&entity.Property(prop).IsModified==true
  27. &&prop.ToLower()!="lastupdateby")
  28. {
  29. AuditLogs.Add(new AuditLog
  30. {
  31. EntityName = entityName,
  32. RecordID = PrimaryKeyValue(entity),
  33. State = state,
  34. ColumnName = prop,
  35. OriginalValue = Convert.ToString(originalValue),
  36. NewValue = Convert.ToString(currentValue),
  37. });
  38. }
  39. }
  40. if (AuditLogs.Count > )
  41. {
  42. TrackingLog.GetXmlForUpdate(doc, AuditLogs);
  43. trackinglogs.Add(new DataLensTrackingLog
  44. {
  45. EntityName = entityName,
  46. Email = this.Email,
  47. XmlDoc = CompressionHelper.Compresse("XmlDoc", new UTF8Encoding().GetBytes(doc.OuterXml)),
  48. CreateTime = DateTime.Now
  49. });
  50. }
  51. break;
  52. case EntityState.Added:
  53. //entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
  54. foreach (string prop in entity.CurrentValues.PropertyNames)
  55. {
  56. AuditLogs.Add(new AuditLog
  57. {
  58. EntityName = entityName,
  59. RecordID = PrimaryKeyValue(entity),
  60. State = state,
  61. ColumnName = prop,
  62. OriginalValue = string.Empty,
  63. NewValue = entity.CurrentValues[prop],
  64. });
  65.  
  66. }
  67. TrackingLog.GetXmlForUpdate(doc, AuditLogs);
  68. trackinglogs.Add(new DataLensTrackingLog
  69. {
  70. EntityName = entityName,
  71. Email = this.Email,
  72. XmlDoc = CompressionHelper.Compresse("XmlDoc", new UTF8Encoding().GetBytes(doc.OuterXml)),
  73. CreateTime = DateTime.Now
  74. });
  75. break;
  76. case EntityState.Deleted:
  77. //entityName = ObjectContext.GetObjectType(entity.Entity.GetType()).Name;
  78. foreach (string prop in entity.OriginalValues.PropertyNames)
  79. {
  80. AuditLogs.Add(new AuditLog
  81. {
  82. EntityName = entityName,
  83. RecordID = PrimaryKeyValue(entity),
  84. State = state,
  85. ColumnName = prop,
  86. OriginalValue = entity.OriginalValues[prop],
  87. NewValue = string.Empty,
  88. });
  89.  
  90. }
  91. TrackingLog.GetXmlForUpdate(doc, AuditLogs);
  92. trackinglogs.Add(new DataLensTrackingLog
  93. {
  94. EntityName = entityName,
  95. Email = this.Email,
  96. XmlDoc = CompressionHelper.Compresse("XmlDoc", new UTF8Encoding().GetBytes(doc.OuterXml)),
  97. CreateTime = DateTime.Now
  98. });
  99. break;
  100. default:
  101. break;
  102. }
  103. }
  104. }
  105. DataTable dt=TypeConvert.ToDataTable(trackinglogs);
  106. SqlDataHelper.SqlBulkCopy(dt, "DataLensTrackingLog", DataBaseType.ConnLogDataStr);
  107. return base.SaveChangesAsync();
  108. }
  109. catch (Exception ex)
  110. {
  111. throw ex;
  112. }
  113. }

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,但是这种方式会有一个问题,假如说存在以下实体

  1. public partial class DataLensDataPointUniverse
  2. {
  3. [Key]
  4. public int DataPointUniverseId { get; set; }
  5. public int DomicileId { get; set; }
  6. public int ShareClassUniverseId { get; set; }
  7. public int DataPointId { get; set; }
  8. public int CollectionStatusId { get; set; }
  9. public Nullable<System.DateTime> CollectionStartDate { get; set; }
  10. public Nullable<System.DateTime> CollectionEndDate { get; set; }
  11. public int CollectionFrequencyId { get; set; }
  12. public int CollectionPriorityId { get; set; }
  13. public string Restrictions { get; set; }
  14. public int FundFormId { get; set; }
  15. public string InterpretationRules { get; set; }
  16. public string Comments { get; set; }
  17. public string QualityMeasureCompleteness { get; set; }
  18. public string QualityMeasureTimeliness { get; set; }
  19. public string QualityMeasureAccuracy { get; set; }
  20. public int FundCollectionRequirementId { get; set; }
  21. public int LEANProjectId { get; set; }
  22. public Nullable<System.Guid> CreateBy { get; set; }
  23. public Nullable<System.Guid> LastUpdateBy { get; set; }
  24. public Nullable<System.DateTime> CreateDate { get; set; }
  25. public Nullable<System.DateTime> LastUpdateDate { get; set; }
  26.  
  27. public virtual DataLensDataPoint DataLensDataPoint { get; set; }
  28. }

这时候获取的实体名字就可能是类似于这种格式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;

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

  1. private string PrimaryKeyValue(DbEntityEntry entry)
  2. {
  3. var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
  4. if (null == objectStateEntry.EntityKey.EntityKeyValues)
  5. {
  6. return string.Empty;
  7. }
  8. return string.Join(",", objectStateEntry.EntityKey.EntityKeyValues.Select(item => item.Value.ToString()).ToArray());
  9. }

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

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

Note:EntityFramework.Extended也支持事务.

EF6 中tracking log使用方法总结的更多相关文章

  1. Swift中自定义Log打印方法

    系统如何调用super方法 系统默认只会在构造函数中,自动调用super.init()方法,而且是在所写方法的尾部进行调用. 在其他函数中,如何需要调用父类的默认实现,都需要手动去实现. 如果在构造函 ...

  2. EF6中使用事务的方法

    默认情况当你执行SaveChanges()的时候(insert update delete)来操作数据库时,Entity Framework会把这个操作包装在一个事务里,当操作结束后,事务也结束了. ...

  3. Java中使用Log的方法

    一.java自带log:java.util.logging.Logger使用三步曲 public class HelloLogWorld { private static String name = ...

  4. Android开发过程中在sh,py,mk文件中添加log信息的方法

    Android开发过程中在sh,py,mk文件中添加log信息的方法 在sh文件中: echo "this is a log info" + $info 在py文件中: print ...

  5. 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测

    如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...

  6. 【翻译自mos文章】在Oracle GoldenGate中循环使用ggserr.log的方法

    在OGG中循环使用ggserr.log的方法: 參考原文: OGG How Do I Recycle The "ggserr.log" File? (Doc ID 967932.1 ...

  7. JavaScript中Math对象的方法介绍

    1.比较最值方法 比较最值有两种方法,max() 和 min() 方法. 1.1 max() 方法,比较一组数值中的最大值,返回最大值. var maxnum = Math.max(12,6,43,5 ...

  8. 在android开发中使用multdex的方法-IT蓝豹为你整理

    Android系统在安装应用时,往往需要优化Dex,而由于处理工具DexOpt对id数目的限制,导致其处理的数目不能超过65536个,因此在Android开发中,需要使用到MultiDex来解决这个问 ...

  9. S5中新增的Array方法详细说明

      ES5中新增的Array方法详细说明 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wor ...

随机推荐

  1. (翻译)正确实施DevOps-The Lay of the Land

    原文地址:http://www.drdobbs.com/architecture-and-design/getting-devops-right-the-lay-of-the-land/2400626 ...

  2. SQL关联查询总结

    employee表: department表: 笛卡儿积: 等值连接: 内连接(和等值连接效果是相同的): 外连接(外连接不仅返回满足条件的记录,还将返回不满足条件的记录)以下是左外连接,右外连接.全 ...

  3. Java序列化格式详解

    RPC的世界,由于涉及到进程间网络远程通信,不可避免的需要将信息序列化后在网络间传送,序列化有两大流派: 文本和二进制. 文本序列化 序列化的实现有很多方式,在异构系统中最常用的就是定义成人类可读的文 ...

  4. 掌握js模板引擎

    最近要做一个小项目,不管是使用angularjs还是reactjs,都觉得大材小用了.其实我可能只需要引入一个jquery,但想到jquery对dom的操作,对于早已习惯了双向绑定模式的我,何尝不是一 ...

  5. UIButton添加倒计时

    最近一个项目有获取手机短信跟邮箱验证码功能, 所以要加一个UIButton倒计时功能 例子代码如下: //获取验证码按钮 - (IBAction)getButtonClick:(UIButton *) ...

  6. 用VC编译lua源码,生成lua语言的解释器和编译器

    用VC编译lua源码,生成lua语言的解释器和编译器 1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编 ...

  7. Atitit oodbms的查询,面向对象的sql查询jpa jpql hql

    Atitit oodbms的查询,面向对象的sql查询jpa jpql hql 1.1. 标准API历史1 1.2. JPA定义了独特的JPQL(Java Persistence Query Lang ...

  8. iOS 和 Android 测试托管平台 FIR.im 的注册与常用功能

    FIR.im  作为专业的 iOS 和 Android 测试包发布网站, 注册超简单,支持输入网址直接下载和二维码扫描下载.功能类似 TestFlight ,但又比它强大,支持游客访问密码,iOS 和 ...

  9. PHP将富文本编辑后的内容,去除样式图片等只保留txt文本内容

    1.从数据库读取富文本内容样式如下: <p style=";text-indent: 0;padding: 0;line-height: 26px"><span ...

  10. CSS伪类与CSS伪元素的区别及由来

    关于两者的区别,其实是很古老的问题.但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手.早些年刚入行的时候,我自己也被深深误导,因 ...