一般系统会有登陆日志,操作日志,异常日志,已经满足大部分的需求了。但是有时候,还是需要Audit 审计日志,审计日志,主要针对数据增,改,删操作数据变化的记录,主要是对数据变化的一个追踪过程。其中主要追踪数据关键点如下

1. 新增 具体新增哪些数据,值是什么,新增人谁。

2. 修改 具体修改哪些数据,之前值是什么,修改后值是什么,修改人谁。

3. 删除 具体删除哪些数据,之前值是什么,删除人谁。

有了这个Audit追踪过程,当那天,用户操作的数据出现问题,你就可以根据这个Audit将数据恢复到某个状态,当然这个Audit,也不仅仅数据出问题才有用,在分析数据时,也有用。

这几年都在做基于ASP.NET MVC & Entity Framework 搭建企业技术框架,很早之前就想自己写一个Audit机制,想着把数据变化保存为json,由于之前公司很多事情所有也没有静下心来想怎么在现有架构上加这块的事情。这几天自己也在找工作(深圳找工作,如果大家的公司缺一个架构的岗位,我可以客串一下,13926537904,不胜感激),所有不忙了,就再次想起Audit来。就开始倒腾起来。

ZZZ Project 这家外国公司,有很多关于.NET和数据访问的项目,有收费的,有开源的,我之前介绍过 Z.ExtensionMethods 一个强大的开源扩展库 就出自该名下,其他有 如下

1. Bulk-Operations ,这个我相信大家也不陌生,Ado.Net 批量操作数据组件 收费

2. EntityFramework-Extensions ,这个Entity Framework 扩展库,这个是EntityFramework 批量操作数据扩展组件 收费

3. EntityFramework-Plus 这个是最近才发布的 Entity Framework + 库,比EntityFramework-Extensions 新增更多的功能。开源免费

4. Dapper-Plus 这个是最近才发布的 Drpper + 库

5. Eval-SQL.NET 关于SQL的,没有使用过,暂时不详细说。

6. Eval-Expression.NET 关于表达式的,没有使用过,暂时不详细说。

等等,还一些我就不一一介绍了,大家可以在下面网站,细看自己感兴趣的。

zzz projects GitHub: https://github.com/zzzprojects

我要说的Audit,在  EntityFramework-Plus 库里面,他有提供,等一下我会实作一下给大家看一下,这个库所提供的功能,如下

如果购买了 EntityFramework-Extensions 这个扩展库,EntityFramework-Extensions 这个库的功能也会包含在里面。

EntityFramework-Plus GitHub 主页 : http://entityframework-plus.net/

EntityFramework-Plus GitHub 源代码: https://github.com/zzzprojects/EntityFramework-Plus

说了一大堆废话,没有入正题,不好意思,开始真正实作 EntityFramework-Plus 之 Audit 部分。

一.  创建解决方案,以及新增基础设施项目(DbContext,Models,Mapping,Demo),这里就不再介绍了,大家参考 Entity Framework 6 开发系列 目录 实作一下即可,就只贴一些关键代码以及项目截图(还未引用EntityFramework-Plus)。

1. 解决方案截图

EntityFrameworkPlus.Demo 项目:控制台程序,应用层 Demo。

EntityFrameworkPlus.DbContext 项目 :DbContext

EntityFrameworkPlus.Mappings 项目:映射模型

EntityFrameworkPlus.Models 项目:模型

2. 关键代码 (还是以订单为义务)

OrderModel

using System;

namespace EntityFrameworkPlus.Models
{
public class OrderModel
{
public Guid OrderGuid { get; set; }
public string OrderNo { get; set; }
public string OrderCreator { get; set; }
public DateTime OrderDateTime { get; set; }
public string OrderStatus { get; set; }
public string Description { get; set; }
public string Creator { get; set; }
public DateTime CreateDateTime { get; set; }
public string LastModifier { get; set; }
public DateTime? LastModifiedDateTime { get; set; }
}
}

OrderMapp

using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
using EntityFrameworkPlus.Models; namespace EntityFrameworkPlus.Mappings
{
public class OrderMap : EntityTypeConfiguration<OrderModel>
{
public OrderMap()
{
this.HasKey(m => m.OrderGuid); this.Property(m => m.OrderGuid)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(m => m.OrderNo)
.IsRequired()
.HasMaxLength(); this.Property(m => m.OrderCreator)
.IsRequired()
.HasMaxLength(); this.Property(m => m.OrderStatus)
.IsRequired()
.HasMaxLength(); this.Property(m => m.Description)
.HasMaxLength(); this.Property(m => m.Creator)
.IsRequired()
.HasMaxLength(); this.Property(m => m.LastModifier)
.HasMaxLength()
.HasMaxLength(); this.ToTable("Sample_Order"); this.Property(m => m.OrderGuid).HasColumnName("OrderGuid");
this.Property(m => m.OrderNo).HasColumnName("OrderNo");
this.Property(m => m.OrderCreator).HasColumnName("OrderCreator");
this.Property(m => m.OrderDateTime).HasColumnName("OrderDateTime");
this.Property(m => m.OrderStatus).HasColumnName("OrderStatus");
this.Property(m => m.Description).HasColumnName("Description");
this.Property(m => m.Creator).HasColumnName("Creator");
this.Property(m => m.CreateDateTime).HasColumnName("CreateDateTime");
this.Property(m => m.LastModifier).HasColumnName("LastModifier");
this.Property(m => m.LastModifiedDateTime).HasColumnName("LastModifiedDateTime");
}
}
}

EntityFrameworkPlusDbContext

using System.Data.Entity;
using EntityFrameworkPlus.Mappings;
using EntityFrameworkPlus.Models; namespace EntityFrameworkPlus.DbContext
{
public class EntityFrameworkPlusDbContext : System.Data.Entity.DbContext
{
public EntityFrameworkPlusDbContext()
: base("EntityFrameworkPlusConnection")
{
}
public DbSet<OrderModel> Orders { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{ modelBuilder.Configurations.Add(new OrderMap()); base.OnModelCreating(modelBuilder);
} }
}

Program

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EntityFrameworkPlus.DbContext;
using EntityFrameworkPlus.Models; namespace EntityFrameworkPlus.Demo
{
class Program
{
static void Main(string[] args)
{
AddOrder();
}
public static void AddOrder()
{
using (var dbContext = new EntityFrameworkPlusDbContext())
{
dbContext.Orders.Add(new OrderModel
{
OrderNo = "ORDER0001",
OrderCreator = "david",
OrderDateTime = DateTime.Now,
OrderStatus = "已出库",
Creator = "david",
CreateDateTime = DateTime.Now
});
dbContext.SaveChanges();
}
}
}
}

3. 项目与项目引用关系(代码图)

二. EntityFramework-Plus 使用

1. 在EntityFrameworkPlus.DbContext,EntityFrameworkPlus.Demo 两个项目中安装 EntityFramework-Plus 库,右键项目 选择“管理NuGet程序包”,联机中,搜索“Z.EntityFramework.Plus”(搜到很多个EntityFramework.Plus 开头组件,大家不要被吓到了,zzz projects 将 Z.EntityFramework.Plus 组件,按照EntityFramework版本分,然后再按照 Z.EntityFramework.Plus 功能来分,比较独立,所以会有这么多个组件,我们这里用的是Entity Framework 6 ,要用到Audit功能),选择 “EntityFramework.Plus (EF6) Audit” 进行安装。

2. EntityFramework.Plus Audit 把数据追踪记录,分成两个表记录

AuditEntries 表 ,记录实体 名称,所属上一级命名空间,状态(增,改,删),状态名称,创建人。

AuditEntryProperties  表,具体数据字段信息,字段名称,关系名称,记录旧,新值。

将 EntityFramework.Plus 提供创建两个表的SQL语句,在自己的数据库里面执行。我的数据库“EntityFrameworkSample”,执行完了,总共就有三个“AuditEntries”,“AuditEntryProperties ”,“Sample_Order”。下面是创建 Audit 相关表SQL,以及数据库结构截图。

CREATE TABLE [dbo].[AuditEntries] (
[AuditEntryID] [int] NOT NULL IDENTITY,
[EntitySetName] [nvarchar](),
[EntityTypeName] [nvarchar](),
[State] [int] NOT NULL,
[StateName] [nvarchar](),
[CreatedBy] [nvarchar](),
[CreatedDate] [datetime] NOT NULL,
CONSTRAINT [PK_dbo.AuditEntries] PRIMARY KEY ([AuditEntryID])
) GO CREATE TABLE [dbo].[AuditEntryProperties] (
[AuditEntryPropertyID] [int] NOT NULL IDENTITY,
[AuditEntryID] [int] NOT NULL,
[RelationName] [nvarchar](),
[PropertyName] [nvarchar](),
[OldValue] [nvarchar](max),
[NewValue] [nvarchar](max),
CONSTRAINT [PK_dbo.AuditEntryProperties] PRIMARY KEY ([AuditEntryPropertyID])
) GO CREATE INDEX [IX_AuditEntryID] ON [dbo].[AuditEntryProperties]([AuditEntryID]) GO ALTER TABLE [dbo].[AuditEntryProperties]
ADD CONSTRAINT [FK_dbo.AuditEntryProperties_dbo.AuditEntries_AuditEntryID]
FOREIGN KEY ([AuditEntryID])
REFERENCES [dbo].[AuditEntries] ([AuditEntryID])
ON DELETE CASCADE GO

3. 在 “EntityFrameworkPlus.DbContext” 项目的“EntityFrameworkPlusDbContext” ,配置Audit 两个表实体集合。配置完成代码如下。

using System.Data.Entity;
using EntityFrameworkPlus.Mappings;
using EntityFrameworkPlus.Models;
using Z.EntityFramework.Plus; namespace EntityFrameworkPlus.DbContext
{
public class EntityFrameworkPlusDbContext : System.Data.Entity.DbContext
{
public EntityFrameworkPlusDbContext()
: base("EntityFrameworkPlusConnection")
{
}
public DbSet<AuditEntry> AuditEntries { get; set; }
public DbSet<AuditEntryProperty> AuditEntryProperties { get; set; }
public DbSet<OrderModel> Orders { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{ modelBuilder.Configurations.Add(new OrderMap()); base.OnModelCreating(modelBuilder);
} }
}

4. 在“EntityFrameworkPlus.Demo” Program 调整代码,使用EntityFramework.Plus Audit 代码,以及增加及调整了 对Sample_Order  增,改,删数据操作。调整代码如下。

using System;
using System.Data.Entity;
using System.Linq;
using EntityFrameworkPlus.DbContext;
using EntityFrameworkPlus.Models;
using Z.EntityFramework.Plus; namespace EntityFrameworkPlus.Demo
{
class Program
{
static void Main(string[] args)
{
AuditManager.DefaultConfiguration.AutoSavePreAction = (context, audit) =>
{
var customAuditEntries = audit.Entries.Select(x => Import(x));
(context as EntityFrameworkPlusDbContext).AuditEntries.AddRange(customAuditEntries);
}; AddOrder();
}
public static void AddOrder()
{
using (var dbContext = new EntityFrameworkPlusDbContext())
{
var audit = new Audit { CreatedBy = "david" };
dbContext.Orders.Add(new OrderModel
{
OrderNo = "ORDER0001",
OrderCreator = "david",
OrderDateTime = DateTime.Now,
OrderStatus = "已出库",
Creator = "david",
CreateDateTime = DateTime.Now
});
dbContext.SaveChanges(audit);
}
}
public static void UpdateOrder()
{
using (var dbContext = new EntityFrameworkPlusDbContext())
{
var audit = new Audit { CreatedBy = "david" };
var orderAsync = dbContext.Orders.FirstAsync();
var order = orderAsync.Result;
order.LastModifier = "davidzhou";
order.LastModifiedDateTime = DateTime.Now;
order.OrderStatus = "已完成";
dbContext.Entry(order);
dbContext.SaveChanges(audit);
}
}
public static void DeleteOrder()
{
using (var dbContext = new EntityFrameworkPlusDbContext())
{
var audit = new Audit { CreatedBy = "david" };
var orderAsync = dbContext.Orders.FirstAsync();
var order = orderAsync.Result;
dbContext.Entry(order).State = EntityState.Deleted;
dbContext.SaveChanges(audit);
}
} public static AuditEntry Import(AuditEntry entry)
{
var customAuditEntry = new AuditEntry
{
EntitySetName = entry.EntitySetName,
EntityTypeName = entry.EntityTypeName,
State = entry.State,
StateName = entry.StateName,
CreatedBy = entry.CreatedBy,
CreatedDate = entry.CreatedDate
};
customAuditEntry.Properties = entry.Properties.Select(x => Import(x)).ToList(); return customAuditEntry;
}
public static AuditEntryProperty Import(AuditEntryProperty property)
{
var customAuditEntry = new AuditEntryProperty
{
RelationName = property.RelationName,
PropertyName = property.PropertyName,
OldValue = property.OldValueFormatted,
NewValue = property.NewValueFormatted
};
return customAuditEntry;
}
}
}

5. 对 Sample_Order 表,做新增 操作,三张表变化如图,我这边就不解释了,大家应该多看得懂。

5. 对 Sample_Order 表,做修改 操作,三张表变化如图,我这边就不解释了,大家应该多看得懂。

5. 对 Sample_Order 表,做删除 操作,三张表变化如图,我这边就不解释了,大家应该多看得懂。

好了,到此博文,已经结束,这里要说明的,Entity Framework Plus Audit 部分,我只使用到一些,还要其他大家可以自行,GitHub 更加深入的了解。

此篇博文的源代码: https://github.com/haibozhou1011/EntityFramework-PlusSample

第一篇 Entity Framework Plus 之 Audit的更多相关文章

  1. 第三篇 Entity Framework Plus 之 Query Cache

    离上一篇博客,快一周,工作太忙,只能利用休息日来写一些跟大家分享,Entity Framework Plus 组件系列文章,之前已经写过两篇 第一篇 Entity Framework Plus 之 A ...

  2. 第二篇 Entity Framework Plus 之 Query Future

    从性能的角度出发,能够减少 增,删,改,查,跟数据库打交道次数,肯定是对性能会有所提升的(这里单纯是数据库部分). 今天主要怎样减少Entity Framework查询跟数据库打交道的次数,来提高查询 ...

  3. 第四篇 Entity Framework Plus 之 Batch Operations

    用 Entity Framework  进行 增,删,改.都是基于Model进行的,且Model都是有状态追踪的.这样Entity Framework才能正常增,删,改. 有时候,要根据某个字段,批量 ...

  4. .NET基础篇——Entity Framework 数据转换层通用类

    在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行CRUD的操作,其中存在相当多的重复代码.为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大家介绍一下Entity F ...

  5. Entity Framework Plus 系列目录

    Entity Framework Plus 系列文章计划的已经全部写完,可能还有其他功能没有写到,希望大家能够多动手,尝试一下使用,一定会给您带来一些帮助的.文章全部写完,也应该出一个目录方便查看,目 ...

  6. Entity Framework 6.1-Code First【转】

      Entity Framework 6.1-Code First 分类: Entity Framework 2014-04-21 14:56 2034人阅读 评论(0) 收藏 举报 entityen ...

  7. Entity Framework 6.0 入门系列 第一篇

    Entity Framework 6.0 入门系列 第一篇 好几年前接触过一些ef感觉不是很好用,废弃.但是 Entity Framework 6.0是经过几个版本优化过的产物,性能和功能不断完善,开 ...

  8. 第一篇:Entity Framework 简介

    先从ORM说起吧,很多年前,由于.NET的开源组件不像现在这样发达,更别说一个开源的ORM框架,出于项目需要,以及当时OOP兴起(总不至于,在项目里面全是SQL语句),就自己开始写ORM框架.要开发O ...

  9. 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述

    微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...

随机推荐

  1. select、poll、epoll之间的区别总结

    select.poll.epoll之间的区别总结 05/05. 2014 select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪 ...

  2. stringstream的基本用法

    原帖地址:https://zhidao.baidu.com/question/580048330.htmlstringstream是字符串流.它将流与存储在内存中的string对象绑定起来.在多种数据 ...

  3. iOS从零开始学习直播之2.采集

      直播的采集由采集的设备(摄像头.话筒)不同分为视频采集和音频采集,本篇文章会分别介绍. 1.采集步骤   1.创建捕捉会话(AVCaptureSession),iOS调用相机和话筒之前都需要创建捕 ...

  4. atitit.attilax的软件 架构 理念.docx

    atitit.attilax的软件 架构 理念.docx 1. 预先规划.1 2. 全体系化1 3. 跨平台2 4. 跨语言2 5. Dsl化2 5.1. 界面ui h5化2 6. 跨架构化2 7. ...

  5. Linux服务器安全配置

    众所周知,网络安全是一个非常重要的课题,而服务器是网络安全中最关键的环节.Linux被认为是一个比较安全的Internet服务器,作为一种开放源代码操作系统,一旦Linux系统中发现有安全漏洞,Int ...

  6. 山寨Unity3D?搜狐畅游的免费开源游戏引擎Genesis-3D

    在CSDN上看到了<搜狐畅游发布3D游戏引擎Genesis-3D 基于MIT协议开源>(http://www.csdn.net/article/2013-11-21/2817585-cha ...

  7. ASP.NET MVC 视图(五)

    ASP.NET MVC 视图(五) 前言 上篇讲解了视图中的分段概念.和分部视图的使用,本篇将会对Razor的基础语法简洁的说明一下,前面的很多篇幅中都有涉及到视图的调用,其中用了很多视图辅助器,也就 ...

  8. ABP源码分析七:Setting 以及 Mail

    本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...

  9. Asp.Net Mvc通用后台管理系统,bootstrap+easyui+权限管理+ORM

    产品清单: 1.整站源码,非编译版,方便进行业务的二次开发 2.通用模块与用户等基础数据的数据库脚本 3.bootstrap3.3.1 AceAdmin模板源码 4.easyui1.3.5源码 5.F ...

  10. 【Win 10应用开发】延迟共享

    延迟共享是啥呢,这么说吧,就是在应用程序打开共享面板选择共享目标时,不会设置要共享的数据,而是等到共享目标请求数据时,才会发送数据,而且,延迟操作可以在后台进行. 这样说似乎过于抽象,最好的诠释方法, ...