网站首页 > 基础教程 正文
Volo.Abp.Data 包定义了在查询数据库时自动过滤数据的服务. ABP定义了一些开箱即用的过滤.
ISoftDelete
将实体标记为已删除,并不是物理删除. 实现 ISoftDelete 接口将你的实体"软删除".
示例:
using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
namespace Acme.BookStore
{
public class Book : AggregateRoot<Guid>, ISoftDelete
{
public string Name { get; set; }
public bool IsDeleted { get; set; } //Defined by ISoftDelete
}
}
ISoftDelete 定义了 IsDeleted 属性. 当你使用仓储删除一条记录时, ABP会自动将 IsDeleted 设置为true,并将删除操作替换为修改操作(如果需要,也可以手动将 IsDeleted 设置为true). 在查询数据库时会自动过滤软删除的实体.
ISoftDelete 过滤默认启用, 想要真正的从数据库删除实体, 需要显式的禁用过滤. 参见下面提到的 IDataFilter 服务.
IMultiTenant
多租户 是创建 SaaS 应用程序的有效方法. 多租户应用程序通常需要在租户间隔离数据. 实现 IMultiTenant 接口使你的实体支持 "多租户".
示例:
using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Acme.BookStore
{
public class Book : AggregateRoot<Guid>, ISoftDelete, IMultiTenant
{
public string Name { get; set; }
public bool IsDeleted { get; set; } //Defined by ISoftDelete
public Guid? TenantId { get; set; } //Defined by IMultiTenant
}
}
IMultiTenant 接口定义了 TenantId 属性用于自动过滤当前租户实体.
IDataFilter
可以使用 IDataFilter 服务控制数据过滤.
示例:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
namespace Acme.BookStore
{
public class MyBookService : ITransientDependency
{
private readonly IDataFilter _dataFilter;
private readonly IRepository<Book, Guid> _bookRepository;
public MyBookService(
IDataFilter dataFilter,
IRepository<Book, Guid> bookRepository)
{
_dataFilter = dataFilter;
_bookRepository = bookRepository;
}
public async Task<List<Book>> GetAllBooksIncludingDeletedAsync()
{
//Temporary disable the ISoftDelete filter
using (_dataFilter.Disable<ISoftDelete>())
{
return await _bookRepository.GetListAsync();
}
}
}
}
- 注入 IDataFilter 服务到你的类中.
- 在 using 语句中使用 Disable 方法创建一个代码块,其中禁用了 ISoftDelete 过滤器(始终与 using 搭配使用,确保代码块执行后将过滤重置为之前的状态).
IDataFilter.Enable 方法可以启用过滤功能, 可以嵌套使用 Enable 和 Disable 方法定义内部作用域.
AbpDataFilterOptions
AbpDataFilterOptions 用于设置数据过滤系统选项.
下面的示例代码在默认情况下禁用了 ISoftDelete 过滤,除非显示启用,在查询数据库时会包含标记为已删除的实体:
Configure<AbpDataFilterOptions>(options =>
{
options.DefaultStates[typeof(ISoftDelete)] = new DataFilterState(isEnabled: false);
});
更改全局过滤的默认值需要小心,特别是在你使用预构建的模块时该模块可能是在默认启用软删除过滤的情况下开发的. 但你可以安全的为自己定义的数据过滤执行此操作.
自定义数据过滤
定义和实现新的过滤很大程度上取决于数据库提供者. ABP为所有的数据库提供者实现了预构建的过滤.
首先为过滤定义一个接口 (如 ISoftDelete 和 IMultiTenant) 然后用实体实现它.
示例:
public interface IIsActive
{
bool IsActive { get; }
}
IIsActive 接口可以过滤活跃/消极数据,任何实体都可以实现它:
public class Book : AggregateRoot<Guid>, IIsActive
{
public string Name { get; set; }
public bool IsActive { get; set; } //Defined by IIsActive
}
EntityFramework Core
ABP使用EF Core的全局过滤系统用于EF Core 集成. 所以它很好的集成到EF Core中,即使你直接使用 DbContext 它也可以正常工作.
实现自定义过滤的最佳方法是为重写你的 DbContext 的 ShouldFilterEntity 和 CreateFilterExpression 方法.
示例:
protected bool IsActiveFilterEnabled => DataFilter?.IsEnabled<IIsActive>() ?? false;
protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType)
{
if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity)))
{
return true;
}
return base.ShouldFilterEntity<TEntity>(entityType);
}
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
var expression = base.CreateFilterExpression<TEntity>();
if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> isActiveFilter =
e => !IsActiveFilterEnabled || EF.Property<bool>(e, "IsActive");
expression = expression == null
? isActiveFilter
: CombineExpressions(expression, isActiveFilter);
}
return expression;
}
- 添加 IsActiveFilterEnabled 属性用于检查是否启用了 IIsActive .
- 重写 ShouldFilterEntity 和 CreateFilterExpression 方法检查给定实体是否实现 IIsActive 接口,在必要时组合表达式.
MongoDB
ABP直接在仓储级别实现数据过滤用于MongoDB 集成. 所以只有正确的使用仓储,它才会工作. 否则你需要手动过滤数据.
目前为MongoDB集成实现数据过滤的最佳方法是重写派生自 MongoDbRepository 仓储的 AddGlobalFilters 方法:
public class BookRepository : MongoDbRepository<BookStoreMongoDbContext, Book, Guid>
{
protected override void AddGlobalFilters(List<FilterDefinition<Book>> filters)
{
if (DataFilter.IsEnabled<IIsActive>())
{
filters.Add(Builders<Book>.Filter.Eq(e => ((IIsActive)e).IsActive, true));
}
}
}
示例中仅为 Book 实体实现了过滤.
如果你想要为所有的实体实现过滤 (实现了 IIsActive 接口的实体),可以创建自己的MongoDB仓储基类并重 写 AddGlobalFilters 方法. 如下所示:
public abstract class MyMongoRepository<TMongoDbContext, TEntity, TKey> : MongoDbRepository<TMongoDbContext, TEntity, TKey>
where TMongoDbContext : IAbpMongoDbContext
where TEntity : class, IEntity<TKey>
{
protected MyMongoRepository(IMongoDbContextProvider<TMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
protected override void AddGlobalFilters(List<FilterDefinition<TEntity>> filters)
{
if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity))
&& DataFilter.IsEnabled<IIsActive>())
{
filters.Add(Builders<TEntity>.Filter.Eq(e => ((IIsActive)e).IsActive, true));
}
}
}
猜你喜欢
- 2024-10-29 57个挑战之57(part6):客户端+web前端+服务端代码实现
- 2024-10-29 技术干货|MongoDB数据库常见操作命令
- 2024-10-29 自建MongoDB实践:MongoDB 分片集群
- 2024-10-29 小程序 随机读取数据并生成分享图片 上手笔记
- 2024-10-29 go-mongox:简单高效,让文档操作和 bson 数据构造更流畅
- 2024-10-29 当MongoDB遇见Spark mongodb campass
- 2024-10-29 MongoDB 5.0 官方文档学习笔记 mongodb教程
- 2024-10-29 好东西,MySQL 数据库 MongoDB详解
- 2024-10-29 MongoDB 入门 day04 mongodb27017
- 2024-10-29 优化MongoDB查询性能:针对百万级数据集的有效策略与实践
- 最近发表
- 标签列表
-
- jsp (69)
- pythonlist (60)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- mysql教程 (60)
- pythonif (86)
- location.href (69)
- deletesql (62)
- c++模板 (62)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- console.table (62)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)