博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解析大型.NET ERP系统 数据审计功能
阅读量:5499 次
发布时间:2019-06-16

本文共 5337 字,大约阅读时间需要 17 分钟。

数据审计,英语表达是Audit,是追踪数据变化的过程,记录数据变化前后的值,供参考分析。通过设置,ERP可以追踪一个表的所有字段的变化,也可以只记录指定的字段的值变化。欧美企业每年都有独立的审计部门,从总经理到下层部门员工,逐个审查过去发生的经济业务的帐面数据与实际是否一致。ERP中的审计功能,通常会记录下一个表字段的值的变化。ERP系统通过LLBL Gen Pro ORM框架做数据访问层,先了解ORM提供的数据审计功能。

审计功能的两个重要部分:记录的变化以及导致变化的动作,持久化变化的数据。

可用于审计的功作:

1 设置属性值。与框架的一致,改变属性的值会引发OnChanged事件,但是通过设置CurrentValue的值则不会审计。

2 移除对象引用。比如销售单实例不再引用客户实体,从客户集合(EntityCollection)中删除客户实体。

3 增加对象引用  与移除对象引用的情况相反,表示对象的属性引用到另一个对象或是实体增加到对象集合中。

4 保存实体  调用SaveEntity方法。

5 更新实体 调用SaveEntity方法。

6 删除实体 调用方法DeleteEntity

7  获取属性值 获取属性值或调用GetCurrentFieldValue方法取值,但是通过获取CurrentValue的值则不会审计。

8  加载实体 调用方法FetchEntity或FetchEntityCollectionNonGeneric。

 

定义一个枚举上面说到的八种情况:

public enum AuditType{        DeleteOfEntity=1,        DirectDeleteOfEntities,        DirectUpdateOfEntities,        DereferenceOfRelatedEntity,        ReferenceOfRelatedEntity,        EntityFieldSet,        InsertOfNewEntity,        UpdateOfExistingEntity}

实体基类EntityBase2已经定义以八种事件中的基础功能,一一列举如下:

1 OnAuditEntityFieldSet 设置属性值

2 OnAuditDereferenceOfRelatedEntity移除对象引用

3 OnAuditReferenceOfRelatedEntity 增加对象引用

4 OnAuditInsertOfNewEntity保存实体

OnAuditUpdateOfExistingEntity更新实体

5 OnAuditDirectUpdateOfEntities 更新实体

6 OnAuditDeleteOfEntity 删除实体

OnAuditDirectDeleteOfEntities 删除实体

7 OnAuditEntityFieldGet获取属性值

8 OnAuditLoadOfEntity加载实体

 

 

创建数据库表AuditSetting 表示存储数据库表是否启用审计功能(Audit)。

CREATE TABLE [dbo].[AuditSetting]( [TableName] [NVARCHAR](100) NOT NULL, CONSTRAINT [PK_AuditSetting] PRIMARY KEY CLUSTERED (    [EntityName] ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]GO

设计三个数据库表,用于存放数据前后的值,用于数据审计。

--Audit  记录用户在每个时间点操作了什么功能CREATE TABLE [dbo].[Audit]([LogNo] [bigint] NOT NULL IDENTITY(1, 1),[Date] [datetime] NULL,[UserId] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,[FunctionCode] [nvarchar] (8) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,[Remarks] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL) ON [PRIMARY]GOALTER TABLE [dbo].[Audit] ADD CONSTRAINT [PK_Audit] PRIMARY KEY CLUSTERED  ([LogNo]) WITH (FILLFACTOR=70) ON [PRIMARY]GO--Audit Table 记录用户操作的功能涉及到的表CREATE TABLE [dbo].[AuditTable]([LogNo] [bigint] NOT NULL,[TableNo] [int] NOT NULL,[Action] [int] NULL,[EntityName] [nvarchar] (60) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,[KeyValue] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL) ON [PRIMARY]GOALTER TABLE [dbo].[AuditTable] ADD CONSTRAINT [PK_AuditTable] PRIMARY KEY CLUSTERED  ([LogNo], [TableNo]) WITH (FILLFACTOR=70) ON [PRIMARY]GOALTER TABLE [dbo].[AuditTable] WITH NOCHECK ADD CONSTRAINT [FK_AuditTrailTableDetail_AuditTrail] FOREIGN KEY ([LogNo]) REFERENCES [dbo].[Audit] ([LogNo]) ON DELETE CASCADE ON UPDATE CASCADEGO--Audit Table column detail 记录列值的新值和旧值CREATE TABLE [dbo].[AuditTableColumn]([LogNo] [bigint] NOT NULL,[TableNo] [int] NOT NULL,[ColumnNo] [int] NOT NULL,[ColumnName] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,[OldValue] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,[NewValue] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]GOALTER TABLE [dbo].[AuditTableColumn] ADD CONSTRAINT [PK_AuditTrailColumnDetail] PRIMARY KEY CLUSTERED  ([LogNo], [TableNo], [ColumnNo]) WITH (FILLFACTOR=70) ON [PRIMARY]GOALTER TABLE [dbo].[AuditTableColumn] WITH NOCHECK ADD CONSTRAINT [FK_AuditTrailColumnDetail_AuditTrailTableDetail] FOREIGN KEY ([LogNo], [TableNo]) REFERENCES [dbo].[AuditTable] ([LogNo], [TableNo]) ON DELETE CASCADE ON UPDATE CASCADEGO
 

定义一个数据审计类型(Facade外观模式),用于数据审计操作。

[DependencyInjectionInfo(typeof(IEntity2), "AuditorToUse")][Serializable]public sealed class DatabaseAuditor : AuditorBase, IDisposable{        #region Class Member Declarations        private AuditEntity _auditTrail;        private AuditTableCollection _auditTrailTableDetails;

因为我用的是LLBL Gen Pro的Adapter模式,所以为数据访问接口增加审计对象。

public sealed class DataAccessAdapter {     private DatabaseAuditor _auditor;     private void InitilaizeAuditor(IEntity2 entity)     {          _auditor = new DatabaseAuditor();          _auditor.Adapter = this;     }     protected override void Dispose(bool isDisposing)     {            if (_auditor != null)            {                _auditor.Dispose();                _auditor = null;            }
}     public override void Commit()     {           if (_auditor != null)           {                _auditor.PersistAuditInfo();                _auditor.Dispose();                _auditor = null;           }
}}
 
 

重写了Commit方法,这表明与数据库相关的操作事务提交时都会调用此方法,用于保存审计信息,也就是值的变化前和变化后的数据。

在保存字段数据时,注意上面的表AuditTableColumn的旧值OldValue和新值NewValue字段都是字符串类型,所以还需要写一个方法,将.NET数据类型转化为字符串格式的值。

如何获取实体属性的旧值与新值,注意上面的代码中用Commit作拦截,保存值数据,数据库事物提交时,值还没有发生更改到数据库中。对比实体的属性新值和数据库中的字段旧值,即可达到这个目的。

foreach (IEntityField2 field in  entity).Fields){       string originalValue = GetFieldOriginalValue(field, false);       string currentValue = GetFieldCurrentValue(field, false);}

取旧值的方法,也就是取ORM属性字段的DbValue,LLBL Gen Pro这一特性在通用功能设计中非常有用。

string fieldOldValue=string.Empty;if (field.DbValue != null && field.DbValue != DBNull.Value){     fieldOldValue= ConvertValueToString(field.DbValue, convertZeroToEmptyString);}
 

最后上一张数据审计查询结果的界面,帮助理解审计功能的设计。

数据审计给企业的审计部门提供了方便,也会降低系统性能,频繁的记录字段的旧值和新值,增加了事务的处理时间。

对一些不重要的业务数据,应该关闭审计选项,提供系统性能。

转载于:https://www.cnblogs.com/JamesLi2015/p/4716951.html

你可能感兴趣的文章
我的友情链接
查看>>
Redis命令大全
查看>>
Entity Framework Code First添加修改及删除外键关联实体
查看>>
CIKERS Shane 20190417
查看>>
使用Daemontools监控管理服务
查看>>
cisco认证
查看>>
Python学习笔记-字典(下)
查看>>
Python命令行模块argparse
查看>>
J2EE中的13种技术规范
查看>>
DNS相关知识和配置(1)
查看>>
Nginx 跨域设置
查看>>
python第三站:运动员数据筛选
查看>>
mysql 之 checkpoint和LSN详解
查看>>
我的友情链接
查看>>
Zend Studio 9.0 最新版下载及安装分享
查看>>
centos下yum安装cacti
查看>>
35 个 Java 代码性能优化总结 1-10
查看>>
nginx 反向代理配置
查看>>
sco2012安装部署
查看>>
nagios详解及安装配置实例
查看>>