ABP官方文档翻译 3.8 数据过滤器

摘要:
数据筛选器描述何时使用预定义的筛选器ISoftDelete?ABP提供了数据过滤器,可用于根据某些规则自动过滤查询。ISoftDelete筛选器始终处于启用状态,除非显示为禁用状态。默认情况下,ABP使用IAbpSession获取当前租户的TenantId,并自动过滤当前租户的查询。如果当前用户未登录系统或是租户用户,ABP将自动禁用IMustHaveTenant筛选器。AbpDataFilters.SoftDelete是一个常量字符串,包含ABP标准软删除筛选器的名称。使用Using语句,可以在某个范围内禁用筛选器。

数据过滤器

介绍

  软删除模式是常用的模式,这种模式并没有从数据库中删除实体而是打上'deleted'的标记。所以,如果实体被软删除,那么它不应该被意外的提取到应用中。为了保证这种事情不会发生,当我们选择实体时,应该添加入‘IsDeleted=false’这样的SQL where条件。这是一个乏味、易忘但很重要的工作。所以,应该由自动的方式来完成。

  ABP提供了数据过滤器,可以用来基于一些规则自动过滤查询。这有一些预定义的过滤器,也可以创建自己的过滤器。

预定义过滤器

ISoftDelete

  Sofe-delete过滤器用来当查询数据库时自动过滤(从结果中提取)已删除的实体。如果一个实体为软删除模式的,它必须实现ISoftDelete接口,这个接口只有IsDeleted属性。示例:

public class Person : Entity, ISoftDelete
{
    public virtual string Name { get; set; }

    public virtual bool IsDeleted { get; set; }
}

  Person实体不会真正从数据库中删除,而是当需要删除它时,将IsDeleted属性设置为true。当使用IRepository.Delete方法(你可以手动设置IsDeleted为true,但是Delete方法是更自然、更好的方式)时,ABP自动完成这个操作。

  实现ISoftDelete接口后,当你从数据库获取People的列表时,已删除的people不会被提取。这里有一个使用person仓储类获取所有people的示例类:

public class MyService
{
    private readonly IRepository<Person> _personRepository;

    public MyService(IRepository<Person> personRepository)
    {
        _personRepository = personRepository;
    }

    public List<Person> GetPeople()
    {
        return _personRepository.GetAllList();
    }
}

  GetPeople方法仅获取Isdeleted=false(没有删除)的person实体。所有的仓储方法和导航属性都可以正常工作。我们可以添加一些其他的Where条件。它会自动添加IsDeleted=false条件到生成的查询语句中。

何时使用?

  ISoftDelete过滤器除非显示的禁用它,否则它总是启用的。

  边注:如果你实现了IDeletionAudited(它扩展了ISoftDelete)接口,ABP会自动设置删除时间和删除用户id。

IMustHaveTenant

  如果你创建了多租户的应用,并把所有的租户数据都存放在一个数据库中,你肯定不想一个租户可以看到其他租户的数据。在这种情况下,你可以实现IMustHaveTenant接口。示例:

public class Product : Entity, IMustHaveTenant
{
    public int TenantId { get; set; }

    public string Name { get; set; }
}

  IMustHaveTenant定义了TenantId用来区分不用租户的实体。ABP默认使用IAbpSession获取当前租户的TenantId,并自动为当前租户过滤查询。

何时使用?

  IMustHaveTenant默认是启用的。

  如果当前用户没有登录到系统或者当前用户是一个租主用户(租户用户是超级用户,可以管理租户和租户数据),ABP自动禁用IMustHaveTenant过滤器。因此,所有租户的所有数据都被提取到应用中。注意这个和安全无关,你应该总是授权敏感的数据。

IMayHaveTenant

  如果实体被租户和租主共享(这意味着一个实体对象可能被一个租户拥有,也可能是租主)。你可以使用IMayHaveTenant过滤器。IMayHaveTenant接口定义了TenantId,但它是nullable。

public class Role : Entity, IMayHaveTenant
{
    public int? TenantId { get; set; }

    public string RoleName { get; set; }
}

  null值意味着是一个租主实体,非null值以为了这个实体数据租户且租户id为TenantId。ABP默认使用IAbpSession获取当前租户的Id。IMayHaveTenant接口不如IMustHaveTenant常见。但是当需要被租户和租主同时使用数据时,你就会需要它。

何时使用

  IMayHaveTenant总是可用的,除非你显示的禁用它。

禁用过滤器

  你可以通过调用DisableFilter方法为每个工作单元禁用过滤器,如下所示:

var people1 = _personRepository.GetAllList();

using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete))
{
    var people2 = _personRepository.GetAllList();                
}

var people3 = _personRepository.GetAllList();

  DisableFilter方法使用一个或多个过滤器的名字作为参数字符串。AbpDataFilters.SoftDelete是一个常量字符串,它包含了ABP标准软删除过滤器的名字。

  people2将包含删除的people,但people1和people3只有未删除的people。使用using语句,你可以在一个范围内禁用过滤器。如果你不使用using语句,过滤器将禁用到当前工作单元的结尾或者你重新显示的启用它。

  你可以注入IUnitOfWorkManager并如在本例中那样使用。你也可以使用CurrentUnitOfWork属性作为捷径,如果你的类集成了一些特殊的基类(如ApplicationService、AbpController、AbpApiController...)。

关于using语句

  当你使用using语句调用DisableFilter方法时,如果这时过滤器可用的,那么调用方法之后过滤器是禁用的,using语句之后会自动重新启用过滤器。但是,如果在using语句之前过滤器已经是禁用的,那么DisableFilter方法实际上什么也没做,using语句之后过滤器仍然保持禁用。

关于多租户

  你可以禁用租户过滤器来查询所有租户的数据。但是记住,这种方法只对单数据库方式有效。如果每一个租户都有单独的数据库,禁用过滤器将不会查询所有租户的所有数据,因为他们在不同的数据库中,甚至在不同的服务器上。参见多租户文档了解更多信息。

全局禁用过滤器

  如果需要,可以全局禁用预定义的过滤器。例如,全局禁用软删除过滤器,在你模块的PreInitialize方法中添加下面的代码:

Configuration.UnitOfWork.OverrideFilter(AbpDataFilters.SoftDelete, false);

启用过滤器

  你可以在工作单元里使用EnableFilter方法来启用过滤器,和DisableFilter相似(功能相反)。EnableFilter方法返回disposable用来在using语句中使用,如果需要,可以自动重新禁用过滤器。

设置过滤器参数

  过滤器可以是参数化的。IMustHaveTenant过滤器就是这种类型的一个示例,因为当前租户id是在运行时决定的。对于这种过滤器,如果需要的话我们可以改变过滤器的值,例如:

CurrentUnitOfWork.SetFilterParameter("PersonFilter", "personId", 42);

  另一个示例:设置IMayHaveTenant过滤器的tenantId值:

urrentUnitOfWork.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, 42);

  SetFilterParameter方法也返回一个IDisposable接口。所以,我们可以使用using语句自动重建之前的值,在using语句之后。

SetTenantId方法

  当你使用SetFilterParameter方法改变MayHaveTenant和MustHaveTenant过滤器的值时,这有一个更好的方式更改租户过滤器:SetTenantId()。SetTenantId为这两个过滤器更改参数值,并且对单数据库和每个租户一个数据库两种类型都有效。所以,建议使用SetTenantId改变租户过滤器的参数值。参见多租户文档了解更多信息。

ORM集成

  预定义过滤器对NHibernate、EntityFramework 6.x和Entity Framework Core同样有效。目前,你只能为Entity Framework 6.x定义自定义过滤器。

Entity Framework

  对Entity Framework集成,使用EntityFramework.DynamicFilters类库实现自动数据过滤。

  为了为Entity Framework创建一个自定义过滤器并集成到ABP,首先我们应该定义一个接口,它将被使用这个过滤器的实体实现。假定,我们想自动通过PersonId过滤实体。示例接口:

public interface IHasPerson
{
    int PersonId { get; set; }
}

  然后我们可以为需要的实体实现这个接口。示例实体如下:

public class Phone : Entity, IHasPerson
{
    [ForeignKey("PersonId")]
    public virtual Person Person { get; set; }
    public virtual int PersonId { get; set; }

    public virtual string Number { get; set; }
}

  我们使用它的规则定义过滤器。在我们的DbContext类,我们重写OnModelCreating并定义过滤器,如下:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Filter("PersonFilter", (IHasPerson entity, int personId) => entity.PersonId == personId, 0);
}

  “PersonFilter”是过滤器唯一的名称。第二个参数定义了过滤器接口和personId过滤器参数(如果过滤器没有参数可以不需要),最后的参数是personId的默认值。

  最后一件事情,我们必须在模块的PreInitialize方法中注册这个过滤器到ABP的工作单元系统中。

Configuration.UnitOfWork.RegisterFilter("PersonFilter", false);

  第一个参数是和我们之前定义的同样的名字。第二个参数标示这个过滤器默认是启用还是禁用。声明这么一个参数化过滤器之后,我们可以在运行时提供给他参数值并使用它。

using (CurrentUnitOfWork.EnableFilter("PersonFilter"))
{
    using(CurrentUnitOfWork.SetFilterParameter("PersonFilter", "personId", 42))
    {
        var phones = _phoneRepository.GetAllList();
        //...
    }
}

  我们可以从一些源获取到personId而不是静态编码。上面的例子是参数化过滤器的。过滤器可以没有或有更多的参数。如果没有参数就不需要设置过滤器参数值。如果默认是启用的就不需要手动启用它(当然,我们可以禁用它)。

EntityFramework.DynaamicFilters文档

  更过关于动态数据过滤器的信息,参见github页上的文档:https://github.com/jcachat/EntityFramework.DynamicFilters

  我们可以为安全、激活/失活实体等等创建自定义过滤器。

其他ORMs

  对于Entity Framework Core和NHibernate,数据过滤是在仓储级别实现的。这就意味着,它只有当你通过仓储查询时才会过滤。如果你直接使用DbContext(对于 EF Core)或通过自定义SQL,你需要自己处理过滤。

Configuration.UnitOfWork.OverrideFilter(AbpDataFilters.SoftDelete, false);


返回主目录

免责声明:文章转载自《ABP官方文档翻译 3.8 数据过滤器》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇可编辑div的createRange()最长上升子序列 题解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Mybatis中的DataSource配置

dataSource 的类型可以配置成其内置类型之一,如 UNPOOLED,POOLED,JNDI。 1、如果将类型设置成 UNPOOLED,MyBatis 会为每一个数据库操作创建一个新的连接,并关闭它。该方式 适用于只有小规模数量并发用户的简单应用程序上。 2、 如果将属性设置成 POOLED,MyBatis 会创建一个数据库连接池,连接池中的一个连接...

01-Hive综述(hive的安装、修改配置、基本使用)

 写在前面的话: 该系列博文是我学习《 Hive源码解析与开发实战》视频课程的一个笔记,或者说总结,暂时没有对视频中的操作去做验证,只是纯粹的学习记录。 有兴趣看该视频的博友可以留言,我会共享出来,相互交流学习 ^.^。 ********************************************************************...

mongodb 安装

a.安装   本人下载的是windows版本的3.2.1mongo,路径为https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.2.1-signed.msi   或者直接去官网也可以http://www.mongodb.org/downloads   不过需要注意的是mo...

oracle优化的几个简单步骤

数据库优化的讨论可以说是一个永恒的主题。资深的Oracle优化人员通常会要求提出性能问题的人对数据库做一个statspack,贴出数据库配置等等。还有的人认为要抓出执行最慢的语句来进行优化。但实际情况是,提出疑问的人很可能根本不懂执行计划,更不要说statspack了。而我认为,数据库优化,应该首先从大的方面考虑:网络、服务器硬件配置、操作系统配置、Ora...

将excel的.xlsx文件转成数据库文件.db的方法

1.下载好工具SQLite Expert Professional 3 ,晚上有很多,自行百度。 2.打开.xls文件,将文件另存为.csv文件。说明一下: 可以将xls文件看作是数据库里的一个表。所以,表名和.xls文件名称一直,里面的字段,就是.xls文件中的字段。 3.打开SQLite Expert Professional 3,新建一个数据库,数据...

Sql Server 常用系统存储过程大全

-- 来源于网络 -- 更详细的介结参考联机帮助文档 xp_cmdshell --*执行DOS各种命令,结果以文本行返回。 xp_fixeddrives --*查询各磁盘/分区可用空间 xp_loginconfig --*报告SQL Server 实例在Windows 上运行时的登录安全配置 xp_logininfo --*返回有关Windows 认证登录...