利用Abp过滤器实现业务数据“回收站”功能

ABP框架中的ISoftDelete与软删除 ABP框架通过接口提供了逻辑删除(也称为软删除)的约定。这个接口中定义了IsDeleted变量,用于标记实体是否被逻辑删除。使用软删除可以让我们在不需要物理删除记录的情况下,将记录标记为已删除,从而保持数据的完整性和可追溯性。 阅读详情

原理

回收站是当用户删除一条记录时,不是直接从数据库中删除,而是将其放入“回收站”,以便用户可以在需要时恢复数据。

在Abp框架中,若实体实现了ISoftDelete,则将实体标记为删除时不是物理删除,而是“软删除”

public interface ISoftDelete
{
    /// <summary>
    /// Used to mark an Entity as 'Deleted'. 
    /// </summary>
    bool IsDeleted { get; set; }
}

当使用仓储删除一条记录时,ABP会自动将 IsDeleted 设置为true,并将删除操作替换为修改操作。 在查询数据库时会自动过滤软删除的实体。

利用这个原理,可以将“软删除”行为认为是放入了“回收站”,而将“恢复”行为认为是从“回收站”中取出。将记录硬删除的行为认为是“永久删除”, 将全部已“软删除”的记录硬删除,则是“清空回收站”

因此我需要实现一个自定义过滤器,用于查看已删除的实体。

创建过滤器

定义仅查看软删除的过滤器,命名"OnlyShowSoftDelete"

public class FileDataFilters
{
    public const string OnlyShowSoftDelete = "OnlyShowSoftDelete";

}

在模块中注册过滤器,isEnabledByDefault参数为false,默认不启用

Configuration.UnitOfWork.RegisterFilter(FileDataFilters.OnlyShowSoftDelete, false);

在DbContext中,增加IsOnlyShowSoftDeleteFilterEnabled属性,用于判断当前的查询上下文中是否启用了“仅查看软删除”过滤器

public bool IsOnlyShowSoftDeleteFilterEnabled => CurrentUnitOfWorkProvider?.Current?.IsFilterEnabled(FileStorage.Uow.FileDataFilters.OnlyShowSoftDelete) == true;

在DbContext中,重写CreateFilterExpression方法,当启用了“仅查看软删除”过滤器时,自动过滤软删除的实体

protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
    var expression = base.CreateFilterExpression<TEntity>();
    if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
    {
        Expression<Func<TEntity, bool>> softDeleteFilter = e => !IsOnlyShowSoftDeleteFilterEnabled || ((ISoftDelete)e).IsDeleted;
        expression = expression == null ? softDeleteFilter : CombineExpressions(expression, softDeleteFilter);
    }

    return expression;
}

使用过滤器

查询

查询正常业务时,不需要对默认的过滤器做操作。

在查看“回收站”中的数据时,需要关闭AbpDataFilters.SoftDelete过滤器,打开FileDataFilters.OnlyShowSoftDelete过滤器。

在使用仓储做任何查询(如: GetAll或Get)之前,加入以下代码:

UnitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete);
UnitOfWorkManager.Current.EnableFilter(FileDataFilters.OnlyShowSoftDelete);

删除

在删除记录时,通过调用仓储的Delete()方法,将记录放入“回收站”中。调用HardDelete()方法,将记录永久删除。


public virtual async Task DeleteAsync(File file, bool isHardDelete = false)
{
    if (isHardDelete)
    {
        await _repository.HardDeleteAsync(file);  //永久删除
    }
    else
    {
        await _repository.DeleteAsync(file);       //放入“回收站”
    }
}

恢复

获取已经“软删除”的记录,调用UnDelete()方法,将记录从“回收站”中取出

UnitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete);
UnitOfWorkManager.Current.EnableFilter(FileDataFilters.OnlyShowSoftDelete);

var currentFile = await _repository.GetAsync(file.Id);
currentFile.UnDelete();

新版Volo.Abp的控制器配置

新版本的Volo.Abp,取消了字符串配置方式,需要为控制器指定一个接口。

创建IOnlyShowSoftDelete接口:

public interface IOnlyShowSoftDelete
{
}

添加配置,将默认的控制器状态设置为不启用

Configure<AbpDataFilterOptions>(options =>
{
    options.DefaultStates[typeof(IOnlyShowSoftDelete)] = new DataFilterState(isEnabled: false);
});

同样,在DbContext中,重写CreateFilterExpression方法,当启用了“仅查看软删除”过滤器时,自动过滤软删除的实体

protected bool IsOnlyShowSoftDeleteFilterEnabled => DataFilter?.IsEnabled<IOnlyShowSoftDelete>() ?? false;

protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
    var expression = base.CreateFilterExpression<TEntity>();

    if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
    {
        Expression<Func<TEntity, bool>> softDeleteFilter = e => !IsOnlyShowSoftDeleteFilterEnabled || ((ISoftDelete)e).IsDeleted;
        expression = expression == null ? softDeleteFilter : CombineExpressions(expression, softDeleteFilter);
    }

    return expression;
}


注入 IDataFilter 服务到你的类中

private readonly IDataFilter _dataFilter;

public MyBookService(IDataFilter dataFilter)
{
    _dataFilter = dataFilter;
}

使用_dataFilter的Enable和Disable方法,启用或禁用过滤器


public async Task<List<Book>> GetAllBooksAsync()
{
    if(input.IncludeTrash)
    {
        //临时显示软删除的记录
        using ( _dataFilter.Disable<ISoftDelete>())
        using ( _dataFilter.Enable<IOnlyShowSoftDelete>())
        {
            return await _bookRepository.GetListAsync();
        }
    }
    else
    {
        return await _bookRepository.GetListAsync();
    }
}

或使用UnitOfWorkManager解析IDataFilter服务

using (input.IncludeTrash ? this.UnitOfWorkManager.Current.ServiceProvider.GetRequiredService<IDataFilter<ISoftDelete>>().Disable() : NullDisposable.Instance)
using (input.IncludeTrash ? this.UnitOfWorkManager.Current.ServiceProvider.GetRequiredService<IDataFilter<IOnlyShowSoftDelete>>().Enable() : NullDisposable.Instance)
{
    return await _bookRepository.GetListAsync();
}
《Android最全面试题-Offer直通车》目录 如今Android求职是僧多粥少,竞争非常激烈,企业招聘时要求很高,本专栏汇聚android面试各种考点,各大公司Android面试题,《Android 最全面试题》将助你全方位提升,助您脱颖而出,早日拿到满意Offer。本专栏汇聚了海量优质内容,文章数量超过100 篇。凭借过硬的质量,每月新增订阅用户数以百计,如今仅需特惠价 9.9 元,限时抢购,后续将逐步恢复原价,早订阅早开启逆袭之旅。精心筹备,整理出一系列超万字精华篇章,累计数十万的 Android 面试题深度剖析。 阅读详情

相关推荐

Brainstorm简单分析近红外数据(fNIRS)(一)

Brainstorm分析fNIRS数据

weixin_43604817的博客 1352

ABP 如何查询出软删除(SoftDelete)数据

介绍 ABP本身是一个包含许多nuget包的模块化框架。它还提供了一个完整的基础架构来开发你自己的具有实体、服务、数据库集成、 API、UI组件等等功能的应用程序模块。 模块类 每个模块都应该定义一个模块类.定义模块类的最简单方法是创建一个派生自AbpModule的类,如下所示: public class BlogModule : AbpModule { } 配置依赖注入和其他模块 ConfigureServices方法 ConfigureServices是将你

研究、探索、分享与成长 1315

基于单片机的继电器参数测试系统设计

由于原有测试系统在参数设置上过于单一,在对继电器测试过程中需要多次进行器件连接,导致对其测试准确度下降,会造成继电器的二次损伤,基于单片机研究继电器参数测试系统的设计方法。在硬件设计上,构建二级模式集散控制框架,利用单片机进行数据采集和处理,满足实时继电器参数数据的同步控制;设计双极性反向比例输出电路,分别利用电极电阻对继电器两侧电压进行放大,实现继电器实时电压的检测。实验结果:以两组类型断电器为测试对象,分别连接示波器进行真实数据采集,在本文系统的应用下所得参数测试结果,与真实的数据相一致,具有实际应用效

weixin_45905610的博客 1439

ABP框架系列之十七:(Data-Filters-数据过滤)

Introduction It's common to use the soft-delete pattern which is used to not delete an entity from database but only mark it as 'deleted'. So, if an entity is soft-deleted, it should not be accidentl...

weixin_33778778的博客 1144

Linux 系统管理员必备:Chrome 企业版离线部署全攻略(含 RPM/DEB 双版本)

本文详细介绍了Linux系统管理员如何离线部署Chrome企业版,涵盖RPM和DEB双版本。从获取官方离线安装包到静默安装、权限配置及企业级策略管理,提供全流程解决方案,特别适合Ubuntu等DEB系系统管理员参考。

f9g0h的博客 487

华为EC6108V9E刷机实战:从U盘准备到开机优化的完整避坑指南

本文提供华为悦盒EC6108V9E刷机与优化的完整实战指南。针对搭载RK3228芯片和安卓4.4.4系统的设备,从型号确认、固件选择、U盘准备,到详细刷机步骤、常见故障排除,以及刷机后的深度性能优化,手把手帮助用户规避风险,让旧盒子焕发新生,成为流畅的全能媒体中心。

weixin_29324401的博客 1194

ABP vNext详细教程——数据过滤器

数据过滤器是ABP vNext的重要功能,在ABP vNext中,软删除、多租户都是以数据过滤器为基础实现的。 这一篇,我将从数据过滤器用法、原理等方面详细介绍数据过滤器

寒冰屋的专栏 1849

F5 Shape逆向工程实战:从美西南航空到xbk的风控突破

本文以美西南航空和xbk为例,深入剖析了F5 Shape风控系统的逆向工程实战。文章拆解了其核心防线,包括通信加密、JSVMP逆向分析和无孔不入的环境指纹检测,并分享了定位Header生成入口、模拟算法输出及构建真实浏览器环境的系统性方法与思路,为合规的技术研究与测试提供参考。

weixin_29327525的博客 1389

ABP理论学习之数据过滤器

返回总目录 本篇目录 介绍 预定义过滤器 关闭过滤器 开启过滤器 设置过滤器参数 定义自定义过滤器 其他ORM 介绍 软删除模式通常用于不会真正从数据库删除一个实体而是仅仅将它标记为"已删除的"。这样,如果一个实体是软删除的,那么它不应该在应用中检索到。为了实现这个目的,我们应该在每一个select实体查询操作中添加一个SQL where条件,如“IsDeleted=false”。这是乏味但...

weixin_34277853的博客 425

非易失存储器读写

24C256、IIC_SCL、IIC_SDA

CT_1104的专栏 2986

Cesium+Vue3教程(003):基于Vue3的Cesium自定义地图和地图叠加

在 Cesium 中,是用于加载地表影像图层的核心接口。通过它,您可以将各种地图服务(如卫星影像、街道地图、自定义瓦片等)加载到 Cesium 的地球上。Cesium 提供了多个内置的。

WwLK123的博客 635

ABP : 软删除过滤器相关QA

软删除过滤器是一种常见的技术,用于在数据库中标记记录已被删除,而不是实际删除记录。通过禁用软删除过滤器,您可以查询已被标记为删除的记录。在ABP框架中,软删除过滤器是一种常见的技术,用于在多租户应用程序中实现数据隔离。软删除过滤器的作用是在数据库中标记记录已被删除,而不是实际删除记录。软删除不会从数据库中永久删除数据,而是将其标记为已删除状态,这样可以在需要时恢复数据。要在ABP框架中使用软删除过滤器,您需要在应用程序模块中启用它,并将其应用于实体。在 ABP 框架中,软删除和硬删除的实现是由实体的。

dongnihao的博客 686

详解AUTOSAR:专栏总述

本专栏系统介绍AUTOSAR规范及车用控制器软件开发,内容覆盖基础架构、SWC/RTE、通信栈、诊断、存储、安全、看门狗、工具链、环境配置与项目实战,并持续更新各模块的集成机制与工程要点。

不脱发的程序猿 3925

ABP vNext 身份验证登录过滤器

通过过滤器控制身份认证

从入坑到入土 803

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

ABP 软删除ISoftDelete

一、简介   ABP 的软删除是为了,在删除的时候,不是真正的删除数据,是为了保护数据。 二、具体实现   在 Core 层,我们需要这个实体去实现这个 ISoftDelete 接口。实现它的public virtual bool IsDeleted { get; set; } 方法即可。 namespace xxx.xxx.xxxxx { using Abp.Domain.Entities; /// <summary> /// 餐馆招聘 (Mg58I..

xiaosachuchen的专栏 1981

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

ABP官方文档(二十一)【数据过滤器】

3.7 ABP领域层 - 数据过滤器3.7.1 简介在数据库开发中,我们一般会运用逻辑删除模式,即不直接从数据库删除数据,而是标记这笔数据为已删除。因此,如果实体被逻辑删除了,那么它就应该不会在应用程序中被检索到。要达到这种效果,我们需要在每次检索实体的查询语句上添加SQL的Where条件IsDeleted = false。这是个乏味的工作,但它是个容易被忘掉的事情。因此,我们应该要有个自动的机制来

极客神殿 2567

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Abp 数据过滤获取AbpUser表数据

使用zero模块的时候,一直获取不到Abpuser中的其他数据,经问群里,是取消数据过滤,代码如下  ///禁用数据过滤            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant, AbpDataFilters.MustHaveTenant))            {          

wang4978的专栏 4440

ABP框架使用拦截器动态配置租户过滤器

文章目录前言具体实现 前言 最近项目要求在ABP框架中根据TenantId是否为空来配置是否禁用租户过滤器。ABP自身给我我们禁用租户过滤器的两种方法官方文档 方法一:使用工作单元 using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant)) { var people2 = _personR...

Caco 的博客 1938

ABP中的数据过滤器

 本文首先介绍了ABP内置的软删除过滤器(ISoftDelete)和多租户过滤器(IMultiTenant),然后介绍了如何实现一个自定义过滤器,最后介绍了在软件开发过程中遇到的实际问题,同时给出了解决问题的一个未必最优的思路。...

寒冰屋的专栏 477

ABP core 重写默认过滤器 实现自定义 errorcode

针对自定义statscode的需求,我们需要重写ABP框架的两个默认过滤器 1,授权过滤器 /// <summary> /// 权限验证过滤器 /// </summary> public class AuthorizationFilter : IAsyncAuthorizationFilter, ITransientDepe...

weixin_30527423的博客 1615

ABP框架增删改查(统一格式 增删改)基础

ABP框架增删改查(统一格式 增删改)基础

guocs415的博客 2537

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 207

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 146

Docker Compose:搭建本地多服务开发环境

从一个 Java API、PostgreSQL 和 Redis 开始,配置服务名、端口、环境变量、健康检查、数据卷和依赖关系。理解 Compose 文件如何被解析、项目如何隔离,以及哪些数据不能依赖“重建容器”保留,能够把个人开发环境整理成团队可复用的启动入口。

m0_62221377的博客 462
上一篇: 怎样优雅地增删查改(八):按用户关系查询
下一篇: 怎样优雅地增删查改(九):按日期范围查询
林晓lx
林晓lx 2017年优快云移动跨平台大赛优秀奖获得者 2017年优快云移动跨平台大赛优秀奖获得者
博客等级 码龄15年 3761粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林晓lx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值