在操作数据记录时,对重要的数据,我们需要记录每一次的变更,有没有好的方法呢?
在通用权限管理系统中提供了记录数据表信息变更的方法。
一、先看看效果截图
二、再看看修改记录表的表结构
三、对该表访问的业务类
1 public partial class ModifyRecordManager : BaseManager, IBaseManager 2 { 3 /// <summary> 4 /// 构造函数 5 /// </summary> 6 public ModifyRecordManager() 7 { 8 if (base.dbHelper == null) 9 { 10 base.dbHelper = DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection); 11 } 12 if (string.IsNullOrEmpty(base.CurrentTableName)) 13 { 14 base.CurrentTableName = ZTO_QUOTE_MODIFYRECORDEntity.TableName; 15 } 16 base.PrimaryKey = "Id"; 17 } 18 19 /// <summary> 20 /// 构造函数 21 /// <param name="tableName">指定表名</param> 22 /// </summary> 23 public ModifyRecordManager(string tableName) 24 { 25 base.CurrentTableName = tableName; 26 } 27 28 /// <summary> 29 /// 构造函数 30 /// </summary> 31 /// <param name="dbHelper">数据库连接</param> 32 public ModifyRecordManager(IDbHelper dbHelper) 33 : this() 34 { 35 DbHelper = dbHelper; 36 } 37 38 /// <summary> 39 /// 构造函数 40 /// </summary> 41 /// <param name="userInfo">用户信息</param> 42 public ModifyRecordManager(BaseUserInfo userInfo) 43 : this() 44 { 45 UserInfo = userInfo; 46 } 47 48 /// <summary> 49 /// 构造函数 50 /// </summary> 51 /// <param name="userInfo">用户信息</param> 52 /// <param name="tableName">指定表名</param> 53 public ModifyRecordManager(BaseUserInfo userInfo, string tableName) 54 : this(userInfo) 55 { 56 base.CurrentTableName = tableName; 57 } 58 59 /// <summary> 60 /// 构造函数 61 /// </summary> 62 /// <param name="dbHelper">数据库连接</param> 63 /// <param name="userInfo">用户信息</param> 64 public ModifyRecordManager(IDbHelper dbHelper, BaseUserInfo userInfo) 65 : this(dbHelper) 66 { 67 UserInfo = userInfo; 68 } 69 70 /// <summary> 71 /// 构造函数 72 /// </summary> 73 /// <param name="dbHelper">数据库连接</param> 74 /// <param name="userInfo">用户信息</param> 75 /// <param name="tableName">指定表名</param> 76 public ModifyRecordManager(IDbHelper dbHelper, BaseUserInfo userInfo, string tableName) 77 : this(dbHelper, userInfo) 78 { 79 base.CurrentTableName = tableName; 80 } 81 82 /// <summary> 83 /// 添加, 这里可以人工干预,提高程序的性能 84 /// </summary> 85 /// <param name="entity">实体</param> 86 /// <param name="identity">自增量方式,表主键是否采用自增的策略</param> 87 /// <param name="returnId">返回主键,不返回程序允许速度会快,主要是为了主细表批量插入数据优化用的</param> 88 /// <returns>主键</returns> 89 public string Add(ZTO_QUOTE_MODIFYRECORDEntity entity, bool identity = true, bool returnId = true) 90 { 91 this.Identity = identity; 92 this.ReturnId = returnId; 93 entity.Id = int.Parse(this.AddObject(entity)); 94 return entity.Id.ToString(); 95 } 96 97 /// <summary> 98 /// 更新 99 /// </summary> 100 /// <param name="entity">实体</param> 101 public int Update(ZTO_QUOTE_MODIFYRECORDEntity entity) 102 { 103 return this.UpdateObject(entity); 104 } 105 106 /// <summary> 107 /// 获取实体 108 /// </summary> 109 /// <param name="id">主键</param> 110 public ZTO_QUOTE_MODIFYRECORDEntity GetObject(string id) 111 { 112 return GetObject(int.Parse(id)); 113 } 114 115 public ZTO_QUOTE_MODIFYRECORDEntity GetObject(int id) 116 { 117 return BaseEntity.Create<ZTO_QUOTE_MODIFYRECORDEntity>(this.GetDataTable(new KeyValuePair<string, object>(this.PrimaryKey, id))); 118 } 119 120 /// <summary> 121 /// 添加实体 122 /// </summary> 123 /// <param name="entity">实体</param> 124 public string AddObject(ZTO_QUOTE_MODIFYRECORDEntity entity) 125 { 126 string key = string.Empty; 127 SQLBuilder sqlBuilder = new SQLBuilder(DbHelper, this.Identity, this.ReturnId); 128 sqlBuilder.BeginInsert(this.CurrentTableName, this.PrimaryKey); 129 if (!this.Identity) 130 { 131 // 这里已经是指定了主键了,所以不需要返回主键了 132 sqlBuilder.ReturnId = false; 133 sqlBuilder.SetValue(this.PrimaryKey, entity.Id); 134 } 135 else 136 { 137 if (!this.ReturnId && (DbHelper.CurrentDbType == CurrentDbType.Oracle || DbHelper.CurrentDbType == CurrentDbType.DB2)) 138 { 139 if (DbHelper.CurrentDbType == CurrentDbType.Oracle) 140 { 141 sqlBuilder.SetFormula(this.PrimaryKey, "SEQ_" + this.CurrentTableName.ToUpper() + ".NEXTVAL "); 142 } 143 if (DbHelper.CurrentDbType == CurrentDbType.DB2) 144 { 145 sqlBuilder.SetFormula(this.PrimaryKey, "NEXT VALUE FOR SEQ_" + this.CurrentTableName.ToUpper()); 146 } 147 } 148 else 149 { 150 if (this.Identity && (DbHelper.CurrentDbType == CurrentDbType.Oracle || DbHelper.CurrentDbType == CurrentDbType.DB2)) 151 { 152 BaseSequenceManager sequenceManager = new BaseSequenceManager(DbHelper); 153 entity.Id = int.Parse(sequenceManager.Increment(this.CurrentTableName)); 154 sqlBuilder.SetValue(this.PrimaryKey, entity.Id); 155 } 156 } 157 } 158 this.SetObject(sqlBuilder, entity); 159 if (UserInfo != null) 160 { 161 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldCreateUserId, UserInfo.Id); 162 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldCreateBy, UserInfo.RealName); 163 } 164 sqlBuilder.SetDBNow(ZTO_QUOTE_MODIFYRECORDEntity.FieldCreateOn); 165 if (this.Identity && (DbHelper.CurrentDbType == CurrentDbType.SqlServer || DbHelper.CurrentDbType == CurrentDbType.Access)) 166 { 167 key = sqlBuilder.EndInsert().ToString(); 168 } 169 else 170 { 171 sqlBuilder.EndInsert(); 172 } 173 if (this.Identity && (DbHelper.CurrentDbType == CurrentDbType.Oracle || DbHelper.CurrentDbType == CurrentDbType.DB2)) 174 { 175 return entity.Id.ToString(); 176 } 177 return key; 178 } 179 180 /// <summary> 181 /// 更新实体 182 /// </summary> 183 /// <param name="entity">实体</param> 184 public int UpdateObject(ZTO_QUOTE_MODIFYRECORDEntity entity) 185 { 186 SQLBuilder sqlBuilder = new SQLBuilder(DbHelper); 187 sqlBuilder.BeginUpdate(this.CurrentTableName); 188 this.SetObject(sqlBuilder, entity); 189 sqlBuilder.SetWhere(this.PrimaryKey, entity.Id); 190 return sqlBuilder.EndUpdate(); 191 } 192 193 // 这个是声明扩展方法 194 partial void SetObjectExpand(SQLBuilder sqlBuilder, ZTO_QUOTE_MODIFYRECORDEntity entity); 195 196 /// <summary> 197 /// 设置实体 198 /// </summary> 199 /// <param name="entity">实体</param> 200 private void SetObject(SQLBuilder sqlBuilder, ZTO_QUOTE_MODIFYRECORDEntity entity) 201 { 202 SetObjectExpand(sqlBuilder, entity); 203 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldNEWKEY, entity.NEWKEY); 204 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldNEWVALUE, entity.NEWVALUE); 205 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldCOLUMNDESCRIPTION, entity.COLUMNDESCRIPTION); 206 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldOLDKEY, entity.OLDKEY); 207 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldOLDVALUE, entity.OLDVALUE); 208 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldRECORDKEY, entity.RECORDKEY); 209 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldCOLUMNCODE, entity.COLUMNCODE); 210 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldTABLEDESCRIPTION, entity.TABLEDESCRIPTION); 211 sqlBuilder.SetValue(ZTO_QUOTE_MODIFYRECORDEntity.FieldTABLECODE, entity.TABLECODE); 212 } 213 214 /// <summary> 215 /// 删除实体 216 /// </summary> 217 /// <param name="id">主键</param> 218 /// <returns>影响行数</returns> 219 public int Delete(int id) 220 { 221 return this.Delete(new KeyValuePair<string, object>(this.PrimaryKey, id)); 222 } 223 }
四、对该表访问的实体类
1 public partial class ModifyRecordEntity : BaseEntity 2 { 3 private string nEWKEY = string.Empty; 4 /// <summary> 5 /// 现值主键 6 /// </summary> 7 public string NEWKEY 8 { 9 get 10 { 11 return nEWKEY; 12 } 13 set 14 { 15 nEWKEY = value; 16 } 17 } 18 19 private string nEWVALUE = string.Empty; 20 /// <summary> 21 /// 现值 22 /// </summary> 23 public string NEWVALUE 24 { 25 get 26 { 27 return nEWVALUE; 28 } 29 set 30 { 31 nEWVALUE = value; 32 } 33 } 34 35 private string cOLUMNDESCRIPTION = string.Empty; 36 /// <summary> 37 /// 列备注 38 /// </summary> 39 public string COLUMNDESCRIPTION 40 { 41 get 42 { 43 return cOLUMNDESCRIPTION; 44 } 45 set 46 { 47 cOLUMNDESCRIPTION = value; 48 } 49 } 50 51 private string createBy = string.Empty; 52 /// <summary> 53 /// 创建用户 54 /// </summary> 55 public string CreateBy 56 { 57 get 58 { 59 return createBy; 60 } 61 set 62 { 63 createBy = value; 64 } 65 } 66 67 private string oLDKEY = string.Empty; 68 /// <summary> 69 /// 原值主键 70 /// </summary> 71 public string OLDKEY 72 { 73 get 74 { 75 return oLDKEY; 76 } 77 set 78 { 79 oLDKEY = value; 80 } 81 } 82 83 private DateTime? createOn = null; 84 /// <summary> 85 /// 创建日期 86 /// </summary> 87 public DateTime? CreateOn 88 { 89 get 90 { 91 return createOn; 92 } 93 set 94 { 95 createOn = value; 96 } 97 } 98 99 private string oLDVALUE = string.Empty; 100 /// <summary> 101 /// 原值 102 /// </summary> 103 public string OLDVALUE 104 { 105 get 106 { 107 return oLDVALUE; 108 } 109 set 110 { 111 oLDVALUE = value; 112 } 113 } 114 115 private string createUserId = string.Empty; 116 /// <summary> 117 /// 创建用户主键 118 /// </summary> 119 public string CreateUserId 120 { 121 get 122 { 123 return createUserId; 124 } 125 set 126 { 127 createUserId = value; 128 } 129 } 130 131 private string rECORDKEY = string.Empty; 132 /// <summary> 133 /// 记录主键 134 /// </summary> 135 public string RECORDKEY 136 { 137 get 138 { 139 return rECORDKEY; 140 } 141 set 142 { 143 rECORDKEY = value; 144 } 145 } 146 147 private string cOLUMNCODE = string.Empty; 148 /// <summary> 149 /// 列名 150 /// </summary> 151 public string COLUMNCODE 152 { 153 get 154 { 155 return cOLUMNCODE; 156 } 157 set 158 { 159 cOLUMNCODE = value; 160 } 161 } 162 163 private Decimal? id = null; 164 /// <summary> 165 /// 主键自增ID 166 /// </summary> 167 public Decimal? Id 168 { 169 get 170 { 171 return id; 172 } 173 set 174 { 175 id = value; 176 } 177 } 178 179 private string tABLEDESCRIPTION = string.Empty; 180 /// <summary> 181 /// 备注 182 /// </summary> 183 public string TABLEDESCRIPTION 184 { 185 get 186 { 187 return tABLEDESCRIPTION; 188 } 189 set 190 { 191 tABLEDESCRIPTION = value; 192 } 193 } 194 195 private string tABLECODE = string.Empty; 196 /// <summary> 197 /// 表名 198 /// </summary> 199 public string TABLECODE 200 { 201 get 202 { 203 return tABLECODE; 204 } 205 set 206 { 207 tABLECODE = value; 208 } 209 } 210 211 /// <summary> 212 /// 从数据行读取 213 /// </summary> 214 /// <param name="dr">数据行</param> 215 protected override BaseEntity GetFrom(IDataRow dr) 216 { 217 GetFromExpand(dr); 218 NEWKEY = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldNEWKEY]); 219 NEWVALUE = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldNEWVALUE]); 220 COLUMNDESCRIPTION = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldCOLUMNDESCRIPTION]); 221 CreateBy = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldCreateBy]); 222 OLDKEY = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldOLDKEY]); 223 CreateOn = BaseBusinessLogic.ConvertToNullableDateTime(dr[ModifyRecordEntity.FieldCreateOn]); 224 OLDVALUE = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldOLDVALUE]); 225 CreateUserId = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldCreateUserId]); 226 RECORDKEY = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldRECORDKEY]); 227 COLUMNCODE = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldCOLUMNCODE]); 228 Id = BaseBusinessLogic.ConvertToNullableDecimal(dr[ModifyRecordEntity.FieldId]); 229 TABLEDESCRIPTION = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldTABLEDESCRIPTION]); 230 TABLECODE = BaseBusinessLogic.ConvertToString(dr[ModifyRecordEntity.FieldTABLECODE]); 231 return this; 232 } 233 234 ///<summary> 235 /// 报价系统修改记录表 236 ///</summary> 237 public static string TableName = "ZTO_QUOTE_MODIFYRECORD"; 238 239 ///<summary> 240 /// 现值主键 241 ///</summary> 242 public static string FieldNEWKEY = "NEWKEY"; 243 244 ///<summary> 245 /// 现值 246 ///</summary> 247 public static string FieldNEWVALUE = "NEWVALUE"; 248 249 ///<summary> 250 /// 列备注 251 ///</summary> 252 public static string FieldCOLUMNDESCRIPTION = "COLUMNDESCRIPTION"; 253 254 ///<summary> 255 /// 创建用户 256 ///</summary> 257 public static string FieldCreateBy = "CreateBy"; 258 259 ///<summary> 260 /// 原值主键 261 ///</summary> 262 public static string FieldOLDKEY = "OLDKEY"; 263 264 ///<summary> 265 /// 创建日期 266 ///</summary> 267 public static string FieldCreateOn = "CreateOn"; 268 269 ///<summary> 270 /// 原值 271 ///</summary> 272 public static string FieldOLDVALUE = "OLDVALUE"; 273 274 ///<summary> 275 /// 创建用户主键 276 ///</summary> 277 public static string FieldCreateUserId = "CreateUserId"; 278 279 ///<summary> 280 /// 记录主键 281 ///</summary> 282 public static string FieldRECORDKEY = "RECORDKEY"; 283 284 ///<summary> 285 /// 列名 286 ///</summary> 287 public static string FieldCOLUMNCODE = "COLUMNCODE"; 288 289 ///<summary> 290 /// 主键自增ID 291 ///</summary> 292 public static string FieldId = "Id"; 293 294 ///<summary> 295 /// 备注 296 ///</summary> 297 public static string FieldTABLEDESCRIPTION = "TABLEDESCRIPTION"; 298 299 ///<summary> 300 /// 表名 301 ///</summary> 302 public static string FieldTABLECODE = "TABLECODE"; 303 }
五、在需要记录表数据变更的的地方:注意,您要记录某个表数据变化,请传入对应的实体。这里使用了反射,只需要传入原来的实体和新的实体即可
/// <summary> /// 根据某个实体保存表数据的变更记录 /// </summary> /// <param name="userInfo"></param> /// <param name="oldEntity"></param> /// <param name="newEntity"></param> public static void AddModifyRecord(BaseUserInfo userInfo, PriceEntity oldEntity, PriceEntity newEntity) { var modifyManager = new ModifyRecordManager(userInfo); try { foreach (var property in typeof(PriceEntity).GetProperties()) { var oldValue = Convert.ToString(property.GetValue(oldEntity, null)); var newValue = Convert.ToString(property.GetValue(newEntity, null)); if (oldValue == newValue) continue; var record = new ZTO_QUOTE_MODIFYRECORDEntity { TABLECODE = PriceEntity.TableName, TABLEDESCRIPTION = GetDataTableComments(PriceEntity.TableName), COLUMNCODE = property.Name, COLUMNDESCRIPTION = GetColumnComments(PriceEntity.TableName + property.Name), RECORDKEY = oldEntity.QUOTE_ID, OLDKEY = oldEntity.QUOTE_ID, OLDVALUE = oldValue, NEWKEY = newEntity.QUOTE_ID, NEWVALUE = newValue }; modifyManager.Add(record, true, true); } } catch (Exception ex) { LogHelper.OracleFatal(userInfo, "主表变更记录出现异常", ex.Message, "AddModifyRecord", typeof(WeiHu), ex); } }
上面表中的GetDataTableComments()是根据表名获取表的备注信息、GetColumnComments()方法是根据列名获取字段的备注信息,实现方法如下:
1、获取表的备注信息,使用了缓存
/// <summary> /// 获取表的备注信息 /// </summary> /// <param name="key"></param> /// <returns></returns> public static string GetDataTableComments(string key) { string cacheKey = "GetK8DataTableComments"; System.Web.Caching.Cache objCache = HttpRuntime.Cache; Dictionary<string, string> dict = (Dictionary<string, string>)objCache[cacheKey]; if (objCache[cacheKey] == null) { lock (ObjLock) { if (objCache[cacheKey] == null) { string commonText = "SELECT TABLE_NAME, COMMENTS FROM USER_TAB_COMMENTS "; IDbHelper dbHelper = DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection); DataTable dt = dbHelper.Fill(commonText); dict = new Dictionary<string, string>(); for (int i = 0; i < dt.Rows.Count; i++) { dict.Add(dt.Rows[i]["TABLE_NAME"].ToString(), dt.Rows[i]["COMMENTS"].ToString()); } objCache.Add(cacheKey, dict, null, DateTime.Now.AddHours(8), Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); if (dict.ContainsKey(key)) { return dict[key]; } } } } if (dict != null) { return dict[key]; } else { return key + "表备注信息没有填写"; } }
2、获得列的备注信息,使用了缓存
/// <summary> /// 获取列的备注信息 /// </summary> /// <param name="key"></param> /// <returns></returns> public static string GetColumnComments(string key) { string cacheKey = "GetK8ColumnComments"; System.Web.Caching.Cache objCache = HttpRuntime.Cache; Dictionary<string, string> dict = (Dictionary<string, string>)objCache[cacheKey]; if (objCache[cacheKey] == null) { lock (ObjLock) { if (objCache[cacheKey] == null) { string commonText = "SELECT TABLE_NAME,COLUMN_NAME,COMMENTS FROM USER_COL_COMMENTS "; IDbHelper dbHelper = DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection); DataTable dt = dbHelper.Fill(commonText); dict = new Dictionary<string, string>(); for (int i = 0; i < dt.Rows.Count; i++) { dict.Add(dt.Rows[i]["TABLE_NAME"].ToString() + dt.Rows[i]["COLUMN_NAME"].ToString(), dt.Rows[i]["COMMENTS"].ToString()); } objCache.Add(cacheKey, dict, null, DateTime.Now.AddHours(8), Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); if (dict.ContainsKey(key)) { return dict[key]; } } } } if (dict != null) { return dict[key]; } else { return key + "列备注信息没有填写"; } }
通过使用上面的方法,我们就可以记录全部表数据的变更记录了,对于排查问题提供了有利的帮助,大家在使用中有什么建议,欢迎提出来。
时间: 2024-10-15 02:32:38