Ef Core花里胡哨系列(1) SafeDelete、ReadOnly、Audit 安全删除、只读、审计等

在软件设计中,软删除是一种常见的数据管理技术,用于标记和隐藏被删除的数据,而不是永久地从数据库中删除它们。软删除通常通过在数据表中添加一个额外的标志列(例如"IsDeleted")来实现。当数据被删除时,该标志列被设置为指示删除状态的值(通常是true或1),而不是直接从数据库中删除数据记录。

使用软删除的主要原因是保留数据的完整性和可追溯性。通过软删除,我们可以避免永久删除数据,从而避免意外或不可逆的数据丢失。软删除还可以帮助我们满足法律、合规性或审计要求,因为我们可以跟踪和记录数据的删除历史。

另一个重要的原因是软删除可以提供更好的用户体验。软删除允许用户恢复被删除的数据,而不必联系管理员或支持团队。这对于误删除或需要恢复数据的情况非常有用。

然而,软删除也有一些潜在的缺点。首先,软删除会增加数据库的存储需求,因为被删除的数据仍然存在于数据库中。其次,软删除可能会导致查询和性能方面的复杂性,因为我们需要在查询中过滤掉已删除的数据。

总之,软删除是一种在软件设计中常见的数据管理技术,它通过标记和隐藏被删除的数据来保留数据的完整性和可追溯性。它提供了更好的用户体验,并满足法律和合规性要求。然而,软删除也有一些潜在的缺点,需要在设计和实现时加以考虑。

定义约束

我们先定义一个安全删除的接口,用于约束对应的实体类。

public interface ISoftDelete
{
public bool IsDeleted{get; set;}
}

通过重写ef core来实现对实现了该接口的成员进行自动处理

通过读取ef core上下文中追踪的实体,如果是继承自ISoftDelete接口,说明便不是直接删除数据,而是软删除即更新数据,将实体对应的IsDeleted标记更改为true,随后将状态改为EntityState.Modified即进行更新操作。

public class SampleDbContext(DbContextOptions<SampleDbContext> options, IServiceProvider serviceProvider)
: DbContext(options)
{ public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
foreach (var entityEntry in ChangeTracker.Entries<IEntity>())
{
if (entityEntry is { Entity: ISafeDelete safeDelete, State: EntityState.Deleted })
{
safeDelete.IsDeleted = true;
entityEntry.State = EntityState.Modified;
}
} return await base.SaveChangesAsync(cancellationToken);
} }

如何查询时自动过滤?

我们通过重写OnModelCreating方法,来预置一些Ef Core的行为,例如HasQueryFilter来预置一个过滤条件,如果是继承自ISoftDelete的实体,那便需要过滤掉已经软删除的数据。

HasQueryFilter仅可以配置一种过滤,且每次查询都会生效。如果有权限相关的管理,建议在仓储层通过权限来实现过滤,更灵活一些或者可以通过在lambda中使用IgnoreQueryFilters()来忽略过滤,例如:DbSet<TEntity>().IgnoreQueryFilters()

public class SampleDbContext(DbContextOptions<SampleDbContext> options, IServiceProvider serviceProvider)
: DbContext(options)
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (typeof(ISafeDelete).IsAssignableFrom(entityType.ClrType))
{
modelBuilder.Entity(entityType.ClrType).HasQueryFilter(GetFilterExpression(entityType.ClrType));
}
} base.OnModelCreating(modelBuilder);
} private Expression<Func<IEntity, bool>> GetFilterExpression(Type type)
{
var parameter = Expression.Parameter(type, "e");
var property = Expression.Property(parameter, nameof(ISafeDelete.IsDeleted));
var body = Expression.Equal(property, Expression.Constant(false));
return Expression.Lambda<Func<IEntity, bool>>(body, parameter);
} public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
foreach (var entityEntry in ChangeTracker.Entries<IEntity>())
{
if (entityEntry is { Entity: ISafeDelete safeDelete, State: EntityState.Deleted })
{
safeDelete.IsDeleted = true;
entityEntry.State = EntityState.Modified;
}
} return await base.SaveChangesAsync(cancellationToken);
}
}

联想扩展

我们通过ISoftDelete约束实现了软删除,那么我们可以实现其它什么操作呢?

我们可以实现一些基于逻辑的业务操作,例如只读,或者是审计信息等等。

只读ReadOnly

在软件设计中,我们一些表可能是记录型数据,是不允许更改的,不能简单的从接口上约束操作,我们可以实现一个IReadOnly接口来标记对应的实体。

public interface IReadOnly
{ }
public class SampleDbContext(DbContextOptions<SampleDbContext> options, IServiceProvider serviceProvider)
: DbContext(options)
{
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
foreach (var entityEntry in ChangeTracker.Entries<IEntity>())
{
// 模式匹配语法,即实体如果继承自 IReadOnly 接口且上下文的状态不是添加或者是无操作,即抛出异常,不允许该操作
if (entityEntry is { Entity: IReadOnly, State: not (EntityState.Added and EntityState.Unchanged) })
{
throw new NotSupportedException();
}
} return await base.SaveChangesAsync(cancellationToken);
}
}

Ef Core花里胡哨系列(1) SafeDelete、ReadOnly、Audit 安全删除、只读、审计等的更多相关文章

  1. 深入理解 EF Core:使用查询过滤器实现数据软删除

    原文:https://bit.ly/2Cy3J5f 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能会去除一些本人实在不知道如何组织 ...

  2. .NET Core工程应用系列(1) 定制化Audit.NET实现自定义AuditTarget

    需求背景 最近在项目上需要增加对用户操作进行审计日志记录的功能,调研了一圈,在.net core生态里,用的最多的是Audit.NET.浏览完这个库的文档后,觉得大致能满足我们的诉求,于是建立一个控制 ...

  3. ASP.NET Boilerplate 学习 AspNet Core2 浏览器缓存使用 c#基础,单线程,跨线程访问和线程带参数 wpf 禁用启用webbroswer右键菜单 EF Core 2.0使用MsSql/MySql实现DB First和Code First ASP.NET Core部署到Windows IIS QRCode.js:使用 JavaScript 生成

    ASP.NET Boilerplate 学习   1.在http://www.aspnetboilerplate.com/Templates 网站下载ABP模版 2.解压后打开解决方案,解决方案目录: ...

  4. 深入理解 EF Core:EF Core 写入数据时发生了什么?

    阅读本文大概需要 14 分钟. 原文:https://bit.ly/2C67m1C 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能 ...

  5. EF Core 2.0使用MsSql/Mysql实现DB First和Code First

    参考地址 EF官网 ASP.NET Core MVC 和 EF Core - 教程系列 环境 Visual Studio 2017 最新版本的.NET Core 2.0 SDK 最新版本的 Windo ...

  6. WithOne 实体关系引起 EF Core 自动删除数据

    最近遇到了一个 EF Core 的恐怖问题,在添加数据时竟然会自动删除数据库中已存在的数据,经过追查发现是一个多余的实体关系配置引起的. modelBuilder.Entity<Question ...

  7. .NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记

    2.4.6 EF Core -- 更新 状态 自动变更检测 不查询删除和更新 并发 状态 Entity State Property State Entity State Added 添加 Uncha ...

  8. 如何使用 EF Core 7 批量删除数据

    在 EF Core 7 中,我们可以使用批量操作来删除多条数据.这种方式与之前的版本有所不同,本文将对比 EFCore 7 和之前版本批量删除数据的不同方式. 删除给定 ID 的数据 在 EF Cor ...

  9. EF Core系列

    一. 二. 三. 系列章节 第一节:EF Core简介和CodeFirst和DBFirst两种映射模式(以SQLite和SQLServer为例) 第X节:XXXXXXXXXXXXXXXXXXXXXXX ...

  10. 9.翻译系列:EF 6以及EF Core中的数据注解特性(EF 6 Code-First系列)

    原文地址:http://www.entityframeworktutorial.net/code-first/dataannotation-in-code-first.aspx EF 6 Code-F ...

随机推荐

  1. Win11专业版电脑无法打开开始菜单的问题

    新系统问题千千万,win11系统占一半.今天又有电脑基地的小伙伴碰到了win11系统无法打开开始菜单的情况,那么应该如何解决这个问题呢?下面,深度技术官网小编就分享详细的处理方法,一起看看小编是如何操 ...

  2. 【AirSim】图像API的使用

    博客地址:https://www.cnblogs.com/zylyehuo/ 参考链接: [AirSim] 具体效果可以关注博主的小红书: 42891122102,上面有效果视频 一.基本信息与Air ...

  3. [AT_abc313_d] Odd or Even

    简单题,但是为什么赛场上 WA 了呢? 弱化题目,设 \(n = k + 1\),发现只需要每一个数不取询问 \(k\) 次,通过前缀和得出. 再设 \(k + 1 \ | \ n\),发现只需要类似 ...

  4. c++ 数据类型及范围

    short: \(-2^{15}\sim 2^{15}-1\) unsigned short: \(0\sim 2^{16}-1\) int: \(-2^{31}\sim 2^{31}-1\) uns ...

  5. U559607 简短的题目-二分+st表

    单调性证明: 对于小数据范围,可以直接考虑暴力枚举长度的方式. 对于额外的 \(20 \%\) 的数据范围,所有的差值加起来肯定是小于等于 \(10 ^ 9\) ,所以不需要操作,直接输出 \(0\) ...

  6. Origin2024如何制作双Y轴图?

    日常科研中,我们经常会用到x-y轴图,但有时候一个x对应两个y值甚至多个y值,那应该怎么做呢?下面给大家分享绘制双Y轴图的操作方法: 操作步骤: 1.先打开Origin2024软件,然后在Book1中 ...

  7. JavaSE-几个典型运算符之间的区别

    几个典型运算符之间的区别 1. i++ 与 ++i i++(后缀递增运算符): 这被称为后缀递增运算符.它首先返回变量 i 的当前值,然后将 i 的值增加 1. 通常用于循环计数器的递增. ++i(前 ...

  8. 2025牛客多校第十场 K.神奇集合 F.老师和Yuuka逛商场 E.老师与好感度 I.矩阵 个人题解

    I.矩阵 数学 #贪心 #构造 题目 思路 首先考虑有数最受条件的约束,因此尝试令数\(x\)沿着某方向前进\(x\)后回到原地: \[\begin{align} (x+x+1)\%n-1&= ...

  9. tortoiseGit 64位简体中文安装教程(附安装包)

    一.简介 TortoiseGit 是一款基于 Git 版本控制系统的图形化客户端工具,专为 Windows 用户设计.它通过右键菜单集成到 Windows 资源管理器中,使用户无需命令行即可轻松执行 ...

  10. vs 调试器:诊断工具意外失败。无法启动标准收集器

    https://blog.csdn.net/zhoukai216/article/details/114391603