9.23 实体/全局查询筛选器

9.23.1 查询筛选器#

通常,我们系统中有一些维护字段,如 IsDeleted 字段,这个字段用来标识用户已经删除的数据,那么我们需要每次查询数据的时候带上这个字段,避免查询出不该出现的数据。

Furion 提供非常灵活方便的全局查询筛选器,能够应用到每一次查询中。

9.23.2 多种筛选器配置#

9.23.2.1 单表筛选器#

单表筛选器就是只针对特定实体进行筛选操作,使用简单,只需要在继承 IEntityTypeBuilder<TEntity> 接口并实现即可,如:

using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
namespace Furion.Core
{
public class Person : Entity, IEntityTypeBuilder<Person>
{
public Person()
{
CreatedTime = DateTime.Now;
IsDeleted = false;
}
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public void Configure(EntityTypeBuilder<Person> entityBuilder, DbContext dbContext, Type dbContextLocator)
{
entityBuilder.HasQueryFilter(u => !u.IsDeleted);
}
}
}

9.23.2.2 全局筛选器#

全局筛选器可以配置所有实体应用筛选器中,无需一个一个去配置。使用方法稍微有些复杂,需要动态构建 Lambda 表达式。

实现全局筛选器依赖于 IModelBuilderFilter 接口,该接口提供两个方法:

  • OnCreating:实体构建之前
  • OnCreated:实体构建之后

通过实现这两个方法即可配置全局过滤器,如:

using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Linq.Expressions;
namespace Furion.EntityFramework.Core
{
[AppDbContext("Sqlite3ConnectionString")]
public class FurDbContext : AppDbContext<FurDbContext>, IModelBuilderFilter<MasterDbContextLocator>
{
public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
{
}
public void OnCreated(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)
{
var expression = BuilderIsDeleteLambdaExpression(entityBuilder);
if (expression == null) return;
entityBuilder.HasQueryFilter(expression);
}
public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)
{
}
/// <summary>
/// 构建 u => EF.Property<bool>(u, "IsDeleted") == false 表达式
/// </summary>
/// <param name="entityBuilder"></param>
/// <returns></returns>
private LambdaExpression BuilderIsDeleteLambdaExpression(EntityTypeBuilder entityBuilder)
{
// 获取实体构建器元数据
var metadata = entityBuilder.Metadata;
if (metadata.FindProperty(nameof(Entity.IsDeleted)) == null) return default;
// 创建表达式元素
var parameter = Expression.Parameter(metadata.ClrType, "u");
var properyName = Expression.Constant(nameof(Entity.IsDeleted));
var propertyValue = Expression.Constant(false);
// 构建表达式 u => EF.Property<bool>(u, "IsDeleted") == false
var expressionBody = Expression.Equal(Expression.Call(typeof(EF), nameof(EF.Property), new[] { typeof(bool) }, parameter, properyName), propertyValue);
var expression = Expression.Lambda(expressionBody, parameter);
return expression;
}
}
}
小建议

如果对动态构建 LambdaExpression 不熟悉的朋友,可以使用 System.Linq.Dynamic.Corehttps://github.com/zzzprojects/System.Linq.Dynamic.Core

9.23.3 反馈与建议#

与我们交流

给 Furion 提 Issue