EF6 中tracking log使用方法总结
先上一段最近项目中的代码,此代码可以放到自己项目中的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(),参考链接为:http://www.cnblogs.com/wujingtao/p/5412329.html
Note:EntityFramework.Extended也支持事务.
EF6 中tracking log使用方法总结的更多相关文章
- Swift中自定义Log打印方法
系统如何调用super方法 系统默认只会在构造函数中,自动调用super.init()方法,而且是在所写方法的尾部进行调用. 在其他函数中,如何需要调用父类的默认实现,都需要手动去实现. 如果在构造函 ...
- EF6中使用事务的方法
默认情况当你执行SaveChanges()的时候(insert update delete)来操作数据库时,Entity Framework会把这个操作包装在一个事务里,当操作结束后,事务也结束了. ...
- Java中使用Log的方法
一.java自带log:java.util.logging.Logger使用三步曲 public class HelloLogWorld { private static String name = ...
- Android开发过程中在sh,py,mk文件中添加log信息的方法
Android开发过程中在sh,py,mk文件中添加log信息的方法 在sh文件中: echo "this is a log info" + $info 在py文件中: print ...
- 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测
如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...
- 【翻译自mos文章】在Oracle GoldenGate中循环使用ggserr.log的方法
在OGG中循环使用ggserr.log的方法: 參考原文: OGG How Do I Recycle The "ggserr.log" File? (Doc ID 967932.1 ...
- JavaScript中Math对象的方法介绍
1.比较最值方法 比较最值有两种方法,max() 和 min() 方法. 1.1 max() 方法,比较一组数值中的最大值,返回最大值. var maxnum = Math.max(12,6,43,5 ...
- 在android开发中使用multdex的方法-IT蓝豹为你整理
Android系统在安装应用时,往往需要优化Dex,而由于处理工具DexOpt对id数目的限制,导致其处理的数目不能超过65536个,因此在Android开发中,需要使用到MultiDex来解决这个问 ...
- S5中新增的Array方法详细说明
ES5中新增的Array方法详细说明 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wor ...
随机推荐
- (翻译)正确实施DevOps-The Lay of the Land
原文地址:http://www.drdobbs.com/architecture-and-design/getting-devops-right-the-lay-of-the-land/2400626 ...
- SQL关联查询总结
employee表: department表: 笛卡儿积: 等值连接: 内连接(和等值连接效果是相同的): 外连接(外连接不仅返回满足条件的记录,还将返回不满足条件的记录)以下是左外连接,右外连接.全 ...
- Java序列化格式详解
RPC的世界,由于涉及到进程间网络远程通信,不可避免的需要将信息序列化后在网络间传送,序列化有两大流派: 文本和二进制. 文本序列化 序列化的实现有很多方式,在异构系统中最常用的就是定义成人类可读的文 ...
- 掌握js模板引擎
最近要做一个小项目,不管是使用angularjs还是reactjs,都觉得大材小用了.其实我可能只需要引入一个jquery,但想到jquery对dom的操作,对于早已习惯了双向绑定模式的我,何尝不是一 ...
- UIButton添加倒计时
最近一个项目有获取手机短信跟邮箱验证码功能, 所以要加一个UIButton倒计时功能 例子代码如下: //获取验证码按钮 - (IBAction)getButtonClick:(UIButton *) ...
- 用VC编译lua源码,生成lua语言的解释器和编译器
用VC编译lua源码,生成lua语言的解释器和编译器 1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编 ...
- Atitit oodbms的查询,面向对象的sql查询jpa jpql hql
Atitit oodbms的查询,面向对象的sql查询jpa jpql hql 1.1. 标准API历史1 1.2. JPA定义了独特的JPQL(Java Persistence Query Lang ...
- iOS 和 Android 测试托管平台 FIR.im 的注册与常用功能
FIR.im 作为专业的 iOS 和 Android 测试包发布网站, 注册超简单,支持输入网址直接下载和二维码扫描下载.功能类似 TestFlight ,但又比它强大,支持游客访问密码,iOS 和 ...
- PHP将富文本编辑后的内容,去除样式图片等只保留txt文本内容
1.从数据库读取富文本内容样式如下: <p style=";text-indent: 0;padding: 0;line-height: 26px"><span ...
- CSS伪类与CSS伪元素的区别及由来
关于两者的区别,其实是很古老的问题.但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手.早些年刚入行的时候,我自己也被深深误导,因 ...