首页 > 其他分享 >利用开源模块EF plus 添加系统审计功能

利用开源模块EF plus 添加系统审计功能

时间:2023-10-17 10:00:45浏览次数:41  
标签:audit dbo AuditEntryID EF State 开源 plus var nvarchar

我参考的网站内容:

https://entityframework-plus.net/ef-core-audit-customization

https://entityframework-plus.net/ef-core-audit-autosave

https://csharp.hotexamples.com/examples/Z.EntityFramework.Plus/Audit/-/php-audit-class-examples.html
https://entityframework-plus.net/audit

https://stackoverflow.com/questions/58711828/how-to-use-code-first-with-entityframework-plus-audit-feature

 在构造器中加入:

        public DbSet<AuditEntry> AuditEntries { get; set; }
        public DbSet<AuditEntryProperty> AuditEntryProperties { get; set; }


        public DataContext()
        {
            AuditManager.DefaultConfiguration.AutoSavePreAction = (context, audit) => AuditEntries.AddRange(audit.Entries);
        }
        public DataContext(CS cs)
             : base(cs)
        {
            AuditManager.DefaultConfiguration.AutoSavePreAction = (context, audit) => AuditEntries.AddRange(audit.Entries);
        }

然后重写SaveChanges 和 SaveChangesAsync

        public override int SaveChanges()
        {  

            var audit = new Audit();
            audit.PreSaveChanges(this);
            var rowAffecteds = base.SaveChanges();
            audit.PostSaveChanges();
            var entries = audit.Entries;

            if (audit.Configuration.AutoSavePreAction != null && entries.FirstOrDefault().EntitySetName != "BaseActionLogs")
            {
                audit.Configuration.AutoSavePreAction(this, audit);
                base.SaveChanges();
            }

            return rowAffecteds;
        }

        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            var audit = new Audit();
            audit.PreSaveChanges(this);
            var rowAffecteds = await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            audit.PostSaveChanges();

            if (audit.Configuration.AutoSavePreAction != null)
            {
                audit.Configuration.AutoSavePreAction(this, audit);
                await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }

            return rowAffecteds;
        }

 

其实以上的Audit也可以用原始的方法实现:

        public override int SaveChanges()
        {
            var changes = this.ChangeTracker.Entries().Where(x => x.State == EntityState.Added ||
                                                                     x.State == EntityState.Modified ||
                                                                     x.State == EntityState.Deleted);

            foreach (var change in changes)
            {
                if (change.State == EntityState.Added)
                {
                    // Log Added
                }
                else if (change.State == EntityState.Modified)
                {
                    // Log Modified
                    var originalValues = change.OriginalValues;
                    var currentValues = change.CurrentValues;

                    foreach (var prop in change.OriginalValues.Properties)
                    {
                        var original = originalValues[prop.Name];
                        var current = currentValues[prop.Name];

                        if (!Equals(original, current))
                        {
                            // log propertyName: original --> current
                        }
                    }
                }
                else if (change.State == EntityState.Deleted)
                {
                    // log deleted
                }
            }
            return base.SaveChanges();
        }

 Database Script

https://entityframework-plus.net/ef-core-audit-autosave

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

 

 

 

标签:audit,dbo,AuditEntryID,EF,State,开源,plus,var,nvarchar
From: https://www.cnblogs.com/axblog/p/17768066.html

相关文章

  • vue3中引入elementplus以及图标(vue3+vuecli)
    开发背景nodev18.17.0(node-v)npmv8.4.1(npm-v)@vue/cli5.0.8(vue-V)0.用命令行安装elementPlusnpminstallelement-plus--save1.elementplus按需手动导入ElementPlus组件很多,如果导入组件太多,为了更好的管理ElementPlus组件,可将组件作为独立的文件,将不同功能逻辑......
  • Educational Codeforces Round 154 (Rated for Div. 2) B. Two Binary Strings
    给定两个长度相等的\(01\)字符串\(a\)和\(b\)。每个字符串都是以\(0\)开始以\(1\)结束。在一步操作中,你可以选择任意一个字符串:选择任意两个位置\(l,r\)满足\(s_l=s_r\),然后让\(\foralli\in[l,r],s_i=s_l\)。询问经过若干次操作后能否使得\(a=b......
  • 【codeforces】cf880div2 vp小结
    碎碎念多测要清空!清空从0开始循环!!!!!!!爆哭不知道因为初始化和清空罚了多少次了呜呜呜呜呜这次真的真的记得清空了,但是因为一直习惯下标从1开始所以导致for循环清空的时候a[0]没有清空A和B简简单单的两个签,但是C的难度就突然升高,补题的时候发现1700的时候真的...犹豫了一下要不要补......
  • Codeforces Round 697 (Div. 3) A. Odd Divisor
    给定一个正整数\(n\),询问是否存在一个\(>1\)的奇数因子。在唯一分解定理下观察\(n\),发现若存在除\(2\)以外的质因子,则\(n\)存在\(>1\)的奇数因子。换句话说\(n\)不是二次幂形式则存在\(>1\)的奇数因子。view#include<bits/stdc++.h>voidsolve(){ long......
  • 03 K8S API资源对象介绍02(Deployment Service DaemonSet StatefulSet)
    一、API资源对象DeploymentDeploymentYANL示例vimnginx-deploy.yamlapiVersion:apps/v1kind:Deploymentmetadata:labels:app:myngname:ng-deployspec:replicas:2##副本数selector:matchLabels:app:myngtemplate:metadata:......
  • Codeforces Round 895 (Div. 3) B. The Corridor or There and Back Again
    你在一个向右延申的无限坐标轴上,且你初始在坐标\(1\)。有\(n\)个陷阱在坐标轴上,第\(i\)个陷阱坐标为\(d_i\),且会在你踩上这个陷阱的\(s_i\)秒过后发动。这时候你不能进入坐标\(d_i\)或者走出坐标\(d_i\)。你需要确定最远的\(k\),保证你能够走到坐标\(k\),并且顺......
  • mybatis、mybatis-plus的二级缓存使用
    需求因有些数据查询量很大,很费数据库资源,且每次查询都是不怎么变更的数据,所以需要通过缓存进行减轻数据库压力,继而选择通过myabtis的二级缓存来实现。使用步棸第一步:yml配置需开启mybatis-plus的二级缓存。#MyBatisPlus的配置项mybatis-plus:configuration:#是否......
  • vue父组件如何获取子组件的ref
    可以在父组件的mounted钩子函数中获取子组件的ref,然后调用子组件的方法来设置当前节点,代码如下://父组件代码<template><SideBarref="sidebar"/></template><script>exportdefault{mounted(){this.$nextTick(()=>{//获取子组件tree的ref......
  • Codeforces Round 896 (Div. 2) A. Make It Zero
    给一个大小为\(n\)的数组\(a\)\((n\geq2)\)。你希望进过一些操作使得\(\foralli,a_i=0\)。在一步操作中,可以选择\(1\leql\leqr\leqn\)并且执行:\(s=\bigoplus_{i=l}^{r}a_i\)。\(\foralll\leqi\leqr,a_i=s\)。输出一个解决方案,使得操作......
  • MyBatis Plus 操作 达梦数据库
    MyBatisPlus操作达梦数据库  一、准备MyBatisPlus相关依赖包MyBatisPlus依赖包下载地址:JAVA_Mybatis_Plus_lib.zip下载加压后,效果如下: ......