欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

打造更好用的 EF 自动审计

程序员文章站 2022-07-09 19:39:36
打造更好用的 EF 自动审计 Intro 上次基于 EF Core 实现了一个自动审计的功能,详细可以参考 ,虽然说多数情况下可以适用,但是因为要显式继承于一个 或 ,所以对代码的侵入性比较强,对于已经无法修改的代码或者已经继承于某一个类了,就无法再继承 了,就没有办法实现自动审计了,在 1.7.0 ......

打造更好用的 ef 自动审计

intro

上次基于 ef core 实现了一个自动审计的功能,详细可以参考 ,虽然说多数情况下可以适用,但是因为要显式继承于一个 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();

审计日志输出结果

打造更好用的 EF 自动审计

打造更好用的 EF 自动审计

more

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

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

reference