打造更好用的 EF 自动审计

Intro

上次基于 EF Core 实现了一个自动审计的功能,详细可以参考 https://www.cnblogs.com/weihanli/p/auto-audit-for-entity-framework.html ,虽然说多数情况下可以适用,但是因为要显式继承于一个 AuditDbContextBaseAuditDbContext,所以对代码的侵入性比较强,对于已经无法修改的代码或者已经继承于某一个类了,就无法再继承 AuditDBContext 了,就没有办法实现自动审计了,在 WeihanLi.EntityFramework 1.7.0 新版本里引入了 AOP 的设计,结合 AOP 来实现就简单很多了,不再需要对原有的 DbContext 有任何修改就可以轻松实现自动审计了,下面来看如何做

实例演示

服务注册

使用 AddProxyDbContext 代替 AddDbContextAddProxyDbContextPool 代替 AddDbContextPool,会自动注册代理服务,以实现 AOP 拦截

var services = new ServiceCollection();
// 使用内置的扩展注册 DbContext 代理服务
//services.AddProxyDbContext<TestDbContext>(options =>
//{
// options
// .UseLoggerFactory(loggerFactory)
// //.EnableDetailedErrors()
// //.EnableSensitiveDataLogging()
// // .UseInMemoryDatabase("Tests")
// .UseSqlServer(DbConnectionString)
// //.AddInterceptors(new QueryWithNoLockDbCommandInterceptor())
// ;
//}); // 使用内置的扩展注册 DbContextPool 代理服务,只是为了方便使用,只会代理 DbContext
services.AddProxyDbContextPool<TestDbContext>(options =>
{
options
.UseLoggerFactory(loggerFactory)
//.EnableDetailedErrors()
//.EnableSensitiveDataLogging()
// .UseInMemoryDatabase("Tests")
.UseSqlServer(DbConnectionString)
//.AddInterceptors(new QueryWithNoLockDbCommandInterceptor())
;
});
// 注册 AOP 服务
services.AddFluentAspects(options =>
{
// 配置使用 AuditDbContextInterceptor 拦截 DbContext 的 SaveChanges 和 SaveChangesAsync 方法
options.InterceptMethod<DbContext>(m =>
m.Name == nameof(DbContext.SaveChanges)
|| m.Name == nameof(DbContext.SaveChangesAsync))
.With<AuditDbContextInterceptor>()
;
});
// 注册 serviceLocator(可选,根据自己需要
DependencyResolver.SetDependencyResolver(services);

审计配置

AuditConfig.Configure(builder =>
{
builder
// 配置操作用户获取方式
.WithUserIdProvider(EnvironmentAuditUserIdProvider.Instance.Value)
//.WithUnModifiedProperty() // 保存未修改的属性,默认只保存发生修改的属性
// 保存更多属性
.EnrichWithProperty("MachineName", Environment.MachineName)
.EnrichWithProperty(nameof(ApplicationHelper.ApplicationName), ApplicationHelper.ApplicationName)
// 保存到自定义的存储
.WithStore<AuditFileStore>()
.WithStore<AuditFileStore>("logs0.log")
// 忽略指定实体
.IgnoreEntity<AuditRecord>()
// 忽略指定实体的某个属性
.IgnoreProperty<TestEntity>(t => t.CreatedAt)
// 忽略所有属性名称为 CreatedAt 的属性
.IgnoreProperty("CreatedAt")
;
});

使用示例

DependencyResolver.TryInvokeService<TestDbContext>(dbContext =>
{
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();
var testEntity = new TestEntity()
{
Extra = new { Name = "Tom" }.ToJson(),
CreatedAt = DateTimeOffset.UtcNow,
};
dbContext.TestEntities.Add(testEntity);
dbContext.SaveChanges(); testEntity.CreatedAt = DateTimeOffset.Now;
testEntity.Extra = new { Name = "Jerry" }.ToJson();
dbContext.SaveChanges(); dbContext.Remove(testEntity);
dbContext.SaveChanges(); var testEntity1 = new TestEntity()
{
Extra = new { Name = "Tom1" }.ToJson(),
CreatedAt = DateTimeOffset.UtcNow,
};
dbContext.TestEntities.Add(testEntity1);
var testEntity2 = new TestEntity()
{
Extra = new { Name = "Tom2" }.ToJson(),
CreatedAt = DateTimeOffset.UtcNow,
};
dbContext.TestEntities.Add(testEntity2);
dbContext.SaveChanges();
});
DependencyResolver.TryInvokeService<TestDbContext>(dbContext =>
{
dbContext.Remove(new TestEntity()
{
Id = 2
});
dbContext.SaveChanges();
});
// disable audit
AuditConfig.DisableAudit();
// enable audit
// AuditConfig.EnableAudit();

审计日志输出结果

More

这样以来就不需要修改原有代码了~~,心情大好,哈哈~

如果应用多有多个 DbContext 有的需要审计,有的不需要审计,则可以在配置的时候指定具体的 DbContext类型如 TestDbContext,这样就只会启用 TestDbContext 的自动审计,别的 DbContext 比如 Test2DbContext 就不会自动审计了

Reference

打造更好用的 EF 自动审计的更多相关文章

  1. EF Core 数据变更自动审计设计

    EF Core 数据变更自动审计设计 Intro 有的时候我们需要知道每个数据表的变更记录以便做一些数据审计,数据恢复以及数据同步等之类的事情, EF 自带了对象追踪,使得我们可以很方便的做一些审计工 ...

  2. 端云协同,打造更易用的AI计算平台

    内容来源:华为开发者大会2021 HMS Core 6 AI技术论坛,主题演讲<端云协同,HUAWEI HiAI Foundation打造更易用的AI计算平台>. 演讲嘉宾:华为海思AI技 ...

  3. 打造百度网盘备份利器:自动备份Linux VPS文件和多线程下载百度网盘资源

    前一段时间国内的各大网盘百度云盘,金山快盘,360云盘,华为网盘为争夺用户上演空间容量博弈,网盘商们还固执地以为中国的网民都不懂网络技术,可以像某公司那样用一些数字的手段来忽悠用户,参与到网盘商的数字 ...

  4. EF自动创建数据库步骤之三(自定义数据库初始器)

    EF自动创建数据库需要我们告诉数据库如何进行初始化:如创建表后是否需要插入一些基础数据,是否 需要创建存储过程.触发器等.还有就是EF有三种初始化方式(参见下面三个类): DropCreateData ...

  5. EF自动创建数据库步骤之一(实体类写法)

    文章演示使用EF自动创建数据库第一个步骤创建实体类. 一.创建表映射实体类 using System; using System.Collections.Generic; using System.C ...

  6. C#连接Oracle数据库,通过EF自动生成与数据库表相关的实体类

    C#连接Oracle数据库,通过EF自动生成与数据库表相关的实体类 ps:如需转载,请在转载文章明显处,i标注作者和原文地址 一.准备条件 需要自己电脑上已经安装了Oracle数据库,并且已经创建了相 ...

  7. AI剪辑和自定义UI,打造更智能的剪辑体验

    为满足开发者构建高效的应用内视频编辑能力,7月的HMS Core 6.0 推出了视频编辑服务(Video Editor Kit),一站式的视频处理能力获得了积极反响.同时,我们也关注到开发者需要集成丰 ...

  8. 产品 | GreatSQL,打造更好的MGR生态

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 用 ...

  9. 全场景AI推理引擎MindSpore Lite, 助力HMS Core视频编辑服务打造更智能的剪辑体验

    移动互联网的发展给人们的社交和娱乐方式带来了很大的改变,以vlog.短视频等为代表的新兴文化样态正受到越来越多人的青睐.同时,随着AI智能.美颜修图等功能在图像视频编辑App中的应用,促使视频编辑效率 ...

随机推荐

  1. Win32程序:与"LPCWSTR"类型的形参不兼容

    出现该问题的原因是通常手动输入的字符串都是LPCSTR类型的, 解决办法如下: 在工程处右键,属性-常规-字符集,将Unicode字符集改为为多字节字符集,应用并确认即可.   字符串常量报错: 在常 ...

  2. wifi无线桥接

    考虑到不同路由器配置上或许有细微差别,我此处路由器是水星(牌子)路由器. 首先需要2台路由器,一台已经能够上网,作为主路由器:另一台啥都没有配置,将来用作副路由器,与主路由器桥接. 步骤: 获取主路由 ...

  3. 分享一下,PHP实现第四方QQ微信扫码登陆,不接入qq互联以及微信开发者平台就可以实现用户对接鹅厂,phpQQ微信扫码登陆

    自己抓的QQ包以及整合了网上一些已经封装好了的代码具体如下:QQ: <?php class QQ extends Curl_Api { //获取登录验证码 public function QRc ...

  4. 浅谈头文件(.h)和源文件(.cpp)的区别

    浅谈头文件(.h)和源文件(.cpp)的区别 本人原来在大一写C的时候,都是所有代码写在一个文件里一锅乱煮.经过自己开始写程序之后,发现一个工程只有一定是由多个不同功能.分门别类展开的文件构成的.一锅 ...

  5. PHP的运行方式(SAPI)

    PHP 常量 PHP_SAPI 具有和 php_sapi_name() 相同的值. define('IS_CGI',(0 === strpos(PHP_SAPI,'cgi') || false !== ...

  6. GoLang——Hello World,打开新世界的大门

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Go语言系列的第一篇文章,我们来聊聊这门新的语言和它的基础语法. 浅谈Golang 作为程序员而言,往往对于学习新的语言都是有抗拒的. ...

  7. MTK Android Camera新增差值

    一. 计算需要的插值 如果原有的插值列表没有我们需要的插值的时候,要通过计算算出符合需求的插值,比如2700W的插值. 具体计算方法如下: 假设像素的长宽分别为X,Y,则插值为XY.由于MTK规定各参 ...

  8. (js描述的)数据结构[哈希表1.1](8)

    (js描述的)数据结构[哈希表1.1](8) 一.数组的缺点 1.数组进行插入操作时,效率比较低. 2.数组基于索引去查找的操作效率非常高,基于内容去查找效率很低. 3.数组进行删除操作,效率也不高. ...

  9. docker-compose 部分错误

    Get https://hub.17kxkx.com/v2/: dial tcp 39.106.209.67:443: connect: connection refused vim /etc/doc ...

  10. 【学习笔记】Iperf3网络性能测试工具

    [学习笔记]Iperf3网络性能测试工具 网络性能评估主要是监测网络带宽的使用率,将网络带宽利用最大化是保证网络性能的基础,但是由于网络设计不合理.网络存在安全漏洞等原因,都会导致网络带宽利用率不高. ...