首页 > 其他分享 >利用Abp过滤器实现业务数据“回收站”功能

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

时间:2023-07-24 12:55:54浏览次数:45  
标签:删除 Abp 过滤器 OnlyShowSoftDelete expression public 回收站

目录

 

原理

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

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

本文来自博客园,作者:林晓lx,转载请注明原文链接:https://www.cnblogs.com/jevonsflash/p/17567356.html

标签:删除,Abp,过滤器,OnlyShowSoftDelete,expression,public,回收站
From: https://www.cnblogs.com/wl-blog/p/17576946.html

相关文章

  • redis 布隆过滤器 详解
    Redis布隆过滤器详解介绍在本文中,我们将详细讨论Redis布隆过滤器的实现过程。布隆过滤器是一种高效的数据结构,它可以用来判断一个元素是否存在于一个集合中,同时也可以用于去重和缓存等场景。在实际应用中,布隆过滤器的效率较高,并且占用的内存较小。什么是布隆过滤器布隆过滤器是......
  • java 拦截、过滤器2
    一、概述在SpringMVC中,除了Filter和Interceptor拦截器外,还有对请求Controller的处理,即对请求和响应内容的处理和对请求参数的处理。二、ControllerAdvice@ControllerAdvice本质上同Component一样,因此也会被当成组件扫描。其中@ExceptionHandler常用到。即抛出的异常会被统一......
  • java拦截Filter和过滤器HandlerInterceptor
    什么是过滤器过滤器Filter是基于Servlet实现,对进入到Servlet的请求拦截。主要用于对字符编码,跨域等问题过滤。如下图:所有的请求和都经过Filter,通过定义Filter,能够对请求进行编码操作。代码是以接口的形式提供:publicinterfaceFilter{defaultvoidinit(FilterConfigfilt......
  • AbpVnext系列<二> 简化项目并启动项目
    一、卸载掉一些暂时用不到的项目如下图红线划掉所示。让项目结构更符合最简化的要求。二、卸载掉删HttpApi.Host引用里的相关EF包,这里不再让api直接操作数据库的相关操作。如果用codefirst的话那就独立一个种子项目。三、修改一下启动项目,讲启动项目改成,并启动。 四、启动......
  • abp-vnext-pro 实战(一,如何增加菜单项)
    1.在前端的vbenadmin目录新增菜单直接在src/router/routes/modules内新增一个模块文件即可。不需要手动引入,放在src/router/routes/modules内的文件会自动被加载。importtype{AppRouteModule}from'/@/router/types';import{LAYOUT}from'/@/router/constant';......
  • ABP Framework - 后台服务
    后台服务在ABPFramework中,后台分为作业和工作者,他们的不同点为:作业持久性的任务,可放在队列中执行。失败后会继续重试工作者在后台运行的独立线程定期运行后台作业依赖包:Volo.Abp.BackgroundJobs.Abstraction创建后台作业后台作业是通过实现IBackgroundJob<TAr......
  • 利用Abp过滤器实现业务数据“回收站”功能
    @目录原理创建过滤器使用过滤器查询删除恢复原理回收站是当用户删除一条记录时,不是直接从数据库中删除,而是将其放入“回收站”,以便用户可以在需要时恢复数据。在Abp框架中,若实体实现了ISoftDelete,则将实体标记为删除时不是物理删除,而是“软删除”publicinterfaceISoftDelete......
  • ABP-配置设置
    配置设置ABP遵循的是约定大于配置,作为约定的内容需要在应用程序中进行设置。定义设置在设置之前需要先定义他,由于ABP是模块化的,不同模块都可以拥有自己独立的设置参数,只需要在类中派生SettingDefinitionProvider类//ABP会自动发现并和注册设置的定义publicclassStudentSet......
  • 视频过滤器LAVFilters安装
    点击下载链接下载安装包双击安装包进行安装全部next下一步即可最后点击Finish完成安装......
  • DRF过滤器
    https://www.django-rest-framework.org/api-guide/filtering一般情况下,我们可以重写DRF视图类的get_queryset()方法来实现查询结果集的过滤。例如,根据request.user来过滤结果集frommyapp.modelsimportPurchasefrommyapp.serializersimportPurchaseSerializerfromrest......