第一篇 Entity Framework Plus 之 Audit
? ? ? 一般系統(tǒng)會(huì)有登陸日志,操作日志,異常日志,已經(jīng)滿足大部分的需求了。但是有時(shí)候,還是需要Audit 審計(jì)日志,審計(jì)日志,主要針對(duì)數(shù)據(jù)增,改,刪操作數(shù)據(jù)變化的記錄,主要是對(duì)數(shù)據(jù)變化的一個(gè)追蹤過程。其中主要追蹤數(shù)據(jù)關(guān)鍵點(diǎn)如下
1. 新增 具體新增哪些數(shù)據(jù),值是什么,新增人誰。
2. 修改 具體修改哪些數(shù)據(jù),之前值是什么,修改后值是什么,修改人誰。
3. 刪除 具體刪除哪些數(shù)據(jù),之前值是什么,刪除人誰。
? ? ? 有了這個(gè)Audit追蹤過程,當(dāng)那天,用戶操作的數(shù)據(jù)出現(xiàn)問題,你就可以根據(jù)這個(gè)Audit將數(shù)據(jù)恢復(fù)到某個(gè)狀態(tài),當(dāng)然這個(gè)Audit,也不僅僅數(shù)據(jù)出問題才有用,在分析數(shù)據(jù)時(shí),也有用。
? ? ? 這幾年都在做基于ASP.NET MVC & Entity Framework 搭建企業(yè)技術(shù)框架,很早之前就想自己寫一個(gè)Audit機(jī)制,想著把數(shù)據(jù)變化保存為json,由于之前公司很多事情所有也沒有靜下心來想怎么在現(xiàn)有架構(gòu)上加這塊的事情。這幾天自己也在找工作(深圳找工作,如果大家的公司缺一個(gè)架構(gòu)的崗位,我可以客串一下,13926537904,不勝感激),所有不忙了,就再次想起Audit來。就開始倒騰起來。
? ? ?ZZZ Project 這家外國(guó)公司,有很多關(guān)于.NET和數(shù)據(jù)訪問的項(xiàng)目,有收費(fèi)的,有開源的,我之前介紹過?Z.ExtensionMethods 一個(gè)強(qiáng)大的開源擴(kuò)展庫?就出自該名下,其他有 如下
1.?Bulk-Operations?,這個(gè)我相信大家也不陌生,Ado.Net 批量操作數(shù)據(jù)組件 收費(fèi)
2.?EntityFramework-Extensions?,這個(gè)Entity Framework 擴(kuò)展庫,這個(gè)是EntityFramework 批量操作數(shù)據(jù)擴(kuò)展組件 收費(fèi)
3.?EntityFramework-Plus?這個(gè)是最近才發(fā)布的 Entity Framework + 庫,比EntityFramework-Extensions?新增更多的功能。開源免費(fèi)
4.?Dapper-Plus?這個(gè)是最近才發(fā)布的 Drpper + 庫?
5.?Eval-SQL.NET?關(guān)于SQL的,沒有使用過,暫時(shí)不詳細(xì)說。
6.?Eval-Expression.NET?關(guān)于表達(dá)式的,沒有使用過,暫時(shí)不詳細(xì)說。
等等,還一些我就不一一介紹了,大家可以在下面網(wǎng)站,細(xì)看自己感興趣的。
zzz projects GitHub: https://github.com/zzzprojects
? ? 我要說的Audit,在??EntityFramework-Plus?庫里面,他有提供,等一下我會(huì)實(shí)作一下給大家看一下,這個(gè)庫所提供的功能,如下
- Batch Operations
- Batch Delete
- Batch Update
- LINQ
- LINQ Dynamic
- Query
- Query Cache
- Query Deferred
- Query Filter
- Query Future
- Query IncludeFilter
- Query IncludeOptimized
- Audit
?
? 如果購買了?EntityFramework-Extensions?這個(gè)擴(kuò)展庫,EntityFramework-Extensions?這個(gè)庫的功能也會(huì)包含在里面。
??EntityFramework-Plus?GitHub 主頁?:?http://entityframework-plus.net/
??EntityFramework-Plus?GitHub 源代碼:?https://github.com/zzzprojects/EntityFramework-Plus
說了一大堆廢話,沒有入正題,不好意思,開始真正實(shí)作?EntityFramework-Plus?之 Audit 部分。
一. ?創(chuàng)建解決方案,以及新增基礎(chǔ)設(shè)施項(xiàng)目(DbContext,Models,Mapping,Demo),這里就不再介紹了,大家參考?Entity Framework 6 開發(fā)系列 目錄?實(shí)作一下即可,就只貼一些關(guān)鍵代碼以及項(xiàng)目截圖(還未引用EntityFramework-Plus)。
? ?1. 解決方案截圖
? ?
EntityFrameworkPlus.Demo 項(xiàng)目:控制臺(tái)程序,應(yīng)用層 Demo。
EntityFrameworkPlus.DbContext 項(xiàng)目 :DbContext
EntityFrameworkPlus.Mappings 項(xiàng)目:映射模型
EntityFrameworkPlus.Models 項(xiàng)目:模型
2. 關(guān)鍵代碼 (還是以訂單為義務(wù))
?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(30);this.Property(m => m.OrderCreator).IsRequired().HasMaxLength(20);this.Property(m => m.OrderStatus).IsRequired().HasMaxLength(30);this.Property(m => m.Description).HasMaxLength(1000);this.Property(m => m.Creator).IsRequired().HasMaxLength(20);this.Property(m => m.LastModifier).HasMaxLength(15).HasMaxLength(20);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. 項(xiàng)目與項(xiàng)目引用關(guān)系(代碼圖)
二.?EntityFramework-Plus?使用
1. 在EntityFrameworkPlus.DbContext,EntityFrameworkPlus.Demo 兩個(gè)項(xiàng)目中安裝?EntityFramework-Plus?庫,右鍵項(xiàng)目 選擇“管理NuGet程序包”,聯(lián)機(jī)中,搜索“Z.EntityFramework.Plus”(搜到很多個(gè)EntityFramework.Plus 開頭組件,大家不要被嚇到了,zzz projects 將?Z.EntityFramework.Plus 組件,按照EntityFramework版本分,然后再按照 Z.EntityFramework.Plus 功能來分,比較獨(dú)立,所以會(huì)有這么多個(gè)組件,我們這里用的是Entity Framework 6 ,要用到Audit功能),選擇 “EntityFramework.Plus (EF6) Audit” 進(jìn)行安裝。
?2.?EntityFramework.Plus Audit 把數(shù)據(jù)追蹤記錄,分成兩個(gè)表記錄
? ?AuditEntries 表 ,記錄實(shí)體 名稱,所屬上一級(jí)命名空間,狀態(tài)(增,改,刪),狀態(tài)名稱,創(chuàng)建人。
? ?AuditEntryProperties ?表,具體數(shù)據(jù)字段信息,字段名稱,關(guān)系名稱,記錄舊,新值。
?將?EntityFramework.Plus 提供創(chuàng)建兩個(gè)表的SQL語句,在自己的數(shù)據(jù)庫里面執(zhí)行。我的數(shù)據(jù)庫“EntityFrameworkSample”,執(zhí)行完了,總共就有三個(gè)“AuditEntries”,“AuditEntryProperties ”,“Sample_Order”。下面是創(chuàng)建 Audit 相關(guān)表SQL,以及數(shù)據(jù)庫結(jié)構(gòu)截圖。?
CREATE TABLE [dbo].[AuditEntries] ([AuditEntryID] [int] NOT NULL IDENTITY,[EntitySetName] [nvarchar](255),[EntityTypeName] [nvarchar](255),[State] [int] NOT NULL,[StateName] [nvarchar](255),[CreatedBy] [nvarchar](255),[CreatedDate] [datetime] NOT NULL,CONSTRAINT [PK_dbo.AuditEntries] PRIMARY KEY ([AuditEntryID]) )GOCREATE TABLE [dbo].[AuditEntryProperties] ([AuditEntryPropertyID] [int] NOT NULL IDENTITY,[AuditEntryID] [int] NOT NULL,[RelationName] [nvarchar](255),[PropertyName] [nvarchar](255),[OldValue] [nvarchar](max),[NewValue] [nvarchar](max),CONSTRAINT [PK_dbo.AuditEntryProperties] PRIMARY KEY ([AuditEntryPropertyID]) )GOCREATE INDEX [IX_AuditEntryID] ON [dbo].[AuditEntryProperties]([AuditEntryID])GOALTER TABLE [dbo].[AuditEntryProperties] ADD CONSTRAINT [FK_dbo.AuditEntryProperties_dbo.AuditEntries_AuditEntryID] FOREIGN KEY ([AuditEntryID]) REFERENCES [dbo].[AuditEntries] ([AuditEntryID]) ON DELETE CASCADEGO
3. 在 “EntityFrameworkPlus.DbContext” 項(xiàng)目的“EntityFrameworkPlusDbContext” ,配置Audit 兩個(gè)表實(shí)體集合。配置完成代碼如下。
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 調(diào)整代碼,使用EntityFramework.Plus Audit 代碼,以及增加及調(diào)整了?對(duì)Sample_Order ?增,改,刪數(shù)據(jù)操作。調(diào)整代碼如下。
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. 對(duì) Sample_Order 表,做新增 操作,三張表變化如圖,我這邊就不解釋了,大家應(yīng)該多看得懂。
5. 對(duì) Sample_Order 表,做修改?操作,三張表變化如圖,我這邊就不解釋了,大家應(yīng)該多看得懂。
5. 對(duì) Sample_Order 表,做刪除?操作,三張表變化如圖,我這邊就不解釋了,大家應(yīng)該多看得懂。
好了,到此博文,已經(jīng)結(jié)束,這里要說明的,Entity Framework Plus Audit 部分,我只使用到一些,還要其他大家可以自行,GitHub 更加深入的了解。
此篇博文的源代碼:?https://github.com/haibozhou1011/EntityFramework-PlusSample
?
轉(zhuǎn)載于:https://www.cnblogs.com/davidzhou/p/5376542.html
總結(jié)
以上是生活随笔為你收集整理的第一篇 Entity Framework Plus 之 Audit的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC 返回json的两种方
- 下一篇: [c/c++] programming之