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

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);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/591194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Server Send Event(基于Http协议的单向消息通信)

简介 Server-Sent Events&#xff08;SSE&#xff09;是一种简单的技术&#xff0c;允许服务器向客户端推送实时更新。在Spring Boot项目中&#xff0c;我们可以使用SseEmitter类来实现SSE功能。本文将详细介绍如何在Spring Boot项目中使用SSE&#xff0c;并给出一个使用示例。…

(九)上市企业实施IPD成功案例分享之——欧普

LED通用照明应用是LED照明应用市场的第一驱动力&#xff0c;由于LED照明技术发展迅速&#xff0c;以及成本快速下降&#xff0c;已成为全球主流照明光源。近年来&#xff0c;通过将智能控制模块嵌入LED通用照明终端&#xff0c;形成了具有自动控制、系统化控制等功能的智能照明…

听GPT 讲Rust源代码--library/panic_unwind

File: rust/library/panic_unwind/src/seh.rs 在Rust源代码中&#xff0c;rust/library/panic_unwind/src/seh.rs这个文件的作用是实现Windows操作系统上的SEH&#xff08;Structured Exception Handling&#xff09;异常处理机制。 SEH是Windows上的一种异常处理机制&#xff…

【Webpack】加载其他型模块

非模块化文件 非模块化文件指的是并不遵循任何一种模块标准的文件。 最常见的就是在 script标签引用jQuey及其各种插件 如何使用 Webpack打包这类文件呢? 其实只要直接引人即可&#xff0c;如: import ./jquery.min.js;但假如我们引人的非模块化文件是以隐式全局变量声明的方…

mongodb启动失败

● mongodb.service - High-performance, schema-free document-oriented database Loaded: loaded (/etc/systemd/system/mongodb.service; disabled; vendor preset: disabled) Active: inactive (dead) 1月 02 10:18:10 lcy mongod[7013]: ERROR: child process fail…

EDI 项目推进流程

EDI 需求确认 交易伙伴发来EDI对接邀请&#xff0c;企业应该如何应对&#xff1f; 首先需要确认EDI需求&#xff0c;通常包括传输协议和报文标准以及传输的业务单据类型。可以向交易伙伴发送以下内容&#xff1a; &#xff08;中文版&#xff09; 与贵司建立EDI连接需要使用…

软件黑盒测试

软件黑盒测试是一种测试方法&#xff0c;它不考虑被测试的软件的内部结构和代码&#xff0c;只关注输入和输出。黑盒测试的目的是验证软件是否符合规格说明书、用户需求和功能规范等要求。通常&#xff0c;黑盒测试包括以下几个步骤&#xff1a; 确定测试目标&#xff1a;确定测…

【温故而知新】vue组件间通信的实现方式

概念 Vue组件间通信的实现方式有以下几种: 父子组件通信:父组件可以通过props属性将数据传递给子组件,子组件可以通过$emit方法触发父组件定义的事件。子组件访问根组件:可以使用provide/inject来实现子组件访问根组件的数据。兄弟组件通信:可以通过一个共同的父组件作为…

【没有哪个港口是永远的停留~论文解读】stable diffusion

了解整个流程&#xff1a; 【第一部分】输入图像 x &#xff08;W*H*3的RGB图像&#xff09;【第一部分】x 经过编码器 生成 (latent 空间的表示) h*w*c (具体设置多少有实验)【第二部分】 逐步加噪得到 &#xff0c;和噪声标签【第二部分】由 Unet&#xff08; &#xff…

Kubernetes(k8s):Namespace详解

Kubernetes&#xff08;k8s&#xff09;&#xff1a;Namespace详解 一、Namespace简介1.1 什么是Namespace1.2 Namespace的作用1.3 命名空间的分类 二、创建和管理Namespace2.1 创建Namespace2.2 管理Namespace 三、Namespace的实战应用3.1 部署多个项目3.2 环境隔离3.3 资源配…

从零开始配置kali2023环境:配置jupyter的多内核环境

在kali2023上面尝试用anaconda3&#xff0c;anaconda2安装实现配置jupyter的多内核环境时出现各种问题&#xff0c;现在可以通过镜像方式解决 1. 搜索镜像 ┌──(holyeyes㉿kali2023)-[~] └─$ sudo docker search anaconda ┌──(holyeyes㉿kali2023)-[~] └─$ sudo …

C++初阶——权限与继承

目录 一、C权限方面的问题 1.访问权限 2.继承机制 二、Cconst引用 const引用有以下几个特点 临时对象引用 常量引用成员变量 二、c引用空间相关问题 三.auto 一、C权限方面的问题 【C入门】访问权限管控和继承机制详解_权限继承功能-CSDN博客文章浏览阅读840次。(2)但…

uniapp-H5项目的坑

先推荐个插件库-非常好用&#xff1a;https://ext.dcloud.net.cn/ 一、uniapp h5 适配pc端 1、问题&#xff1a;屏幕尺寸在400px~960px之间页面排版错乱 2、解决方法&#xff1a;在page.json文件中 "globalStyle": {"navigationStyle": "custom&quo…

YOLOv8训练自己的数据集(超详细)

一、准备深度学习环境 本人的笔记本电脑系统是&#xff1a;Windows10 YOLO系列最新版本的YOLOv8已经发布了&#xff0c;详细介绍可以参考我前面写的博客&#xff0c;目前ultralytics已经发布了部分代码以及说明&#xff0c;可以在github上下载YOLOv8代码&#xff0c;代码文件夹…

LVM和磁盘配额

一&#xff1a;LVM概述&#xff1a; LVM 是 Logical Volume Manager 的简称&#xff0c;译为中文就是逻辑卷管理。 能够在保持现有数据不变的情况下&#xff0c;动态调整磁盘容量&#xff0c;从而提高磁盘管理的灵活性 /boot 分区用于存放引导文件&#xff0c;不能基于LVM创建…

MongoDB vs MySQL:项目选择哪一个数据库系统?

由于市场上有各种可用的数据库&#xff0c;用户经常会就MongoDB与MySQL进行辩论&#xff0c;以找出更好的选择。 使用MySQL等关系数据库的组织在根据不断变化的需求管理和存储数据时可能会面临一定的困难。同时&#xff0c;新公司想知道选择什么数据库&#xff0c;这样他们就不…

【ArcGIS微课1000例】0085:甘肃省白银市平川区4.9级地震震中位置图件制作

据中国地震台网正式测定,12月31日22时27分在甘肃白银市平川区发生4.9级地震,震源深度10公里,震中位于北纬36.74度,东经105.00度。 文章目录 一、白银市行政区划图1. 县级行政区2. 乡镇行政区二、4.9级地震图件制作1. 震中位置2. 影像图3. 震中三维地形一、白银市行政区划图…

【LLM 】7个基本的NLP模型,为ML应用程序赋能

在上一篇文章中&#xff0c;我们已经解释了什么是NLP及其在现实世界中的应用。在这篇文章中&#xff0c;我们将继续介绍NLP应用程序中使用的一些主要深度学习模型。 BERT 来自变压器的双向编码器表示&#xff08;BERT&#xff09;由Jacob Devlin在2018年的论文《BERT:用于语言…

数据结构初阶之栈和队列(C语言版)

数据结构初阶之栈和队列&#xff08;C语言版&#xff09; ✍栈♈栈的结构设计♈栈的各个接口的实现&#x1f47a;StackInit(初始化)&#x1f47a;push&#xff08;入栈&#xff09;&#x1f47a;pop&#xff08;出栈&#xff09;&#x1f47a;获取栈顶元素&#x1f47a;获取栈中…

软件工程期末总结

软件工程期末总结 软件危机出现的原因软件生命周期软件生命周期的概念生命周期的各个阶段 软件开发模型极限编程 可行性研究与项目开发计划需求分析结构化分析的方法结构化分析的图形工具软件设计的原则用户界面设计结构化软件设计面向对象面向对象建模 软件危机出现的原因 忽视…