第一篇 Entity Framework Plus 之 Audit Z.ExtensionMethods 一個強大的開源擴展庫 Entity Framework 6 開發系列 目錄

      通常系統會有登錄日誌,操做日誌,異常日誌,已經知足大部分的需求了。可是有時候,仍是須要Audit 審計日誌,審計日誌,主要針對數據增,改,刪操做數據變化的記錄,主要是對數據變化的一個追蹤過程。其中主要追蹤數據關鍵點以下html

1. 新增 具體新增哪些數據,值是什麼,新增人誰。git

2. 修改 具體修改哪些數據,以前值是什麼,修改後值是什麼,修改人誰。github

3. 刪除 具體刪除哪些數據,以前值是什麼,刪除人誰。數據庫

      有了這個Audit追蹤過程,當那天,用戶操做的數據出現問題,你就能夠根據這個Audit將數據恢復到某個狀態,固然這個Audit,也不單單數據出問題纔有用,在分析數據時,也有用。json

      這幾年都在作基於ASP.NET MVC & Entity Framework 搭建企業技術框架,很早以前就想本身寫一個Audit機制,想着把數據變化保存爲json,因爲以前公司不少事情全部也沒有靜下心來想怎麼在現有架構上加這塊的事情。這幾天本身也在找工做(深圳找工做,若是你們的公司缺一個架構的崗位,我能夠客串一下,13926537904,不勝感激),全部不忙了,就再次想起Audit來。就開始倒騰起來。架構

     ZZZ Project 這家外國公司,有不少關於.NET數據訪問的項目,有收費的,有開源的,我以前介紹過 Z.ExtensionMethods 一個強大的開源擴展庫 就出自該名下,其餘有 以下app

1. Bulk-Operations ,這個我相信你們也不陌生,Ado.Net 批量操做數據組件 收費框架

2. EntityFramework-Extensions ,這個Entity Framework 擴展庫,這個是EntityFramework 批量操做數據擴展組件 收費ide

3. EntityFramework-Plus 這個是最近才發佈的 Entity Framework + 庫,比EntityFramework-Extensions 新增更多的功能。開源免費post

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(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. 項目與項目引用關係(代碼圖)

二. 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](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]) ) GO

CREATE 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]) ) 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

相關文章
相關標籤/搜索