EF Core 2:如何对所有实体应用 HasQueryFilter

问题描述 投票:0回答:4

有什么方法可以将

HasQueryFilter()
全局应用到我的所有实体吗?我不想一一添加
ModelBuilder

modelBuilder.Entity<Manufacturer>().HasQueryFilter(p => p.IsActive);
entity-framework entity-framework-core
4个回答
15
投票

如果您有定义

IsActive
属性的基类或接口,您可以使用过滤所有查询(尝试实现软删除)中的方法。

否则,您可以迭代实体类型,并为具有

bool IsActive
属性的每种类型使用
Expression
类方法动态构建过滤器表达式:

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
    var isActiveProperty = entityType.FindProperty("IsActive");
    if (isActiveProperty != null && isActiveProperty.ClrType == typeof(bool))
    {
        var parameter = Expression.Parameter(entityType.ClrType, "p");
        var filter = Expression.Lambda(Expression.Property(parameter, isActiveProperty.PropertyInfo), parameter);
        entityType.QueryFilter = filter;
    }
}

更新(EF Core 3.0):由于公共元数据 API 发生重大更改(用

Get
/
Set
扩展方法替换许多属性),最后一行变为

entityType.SetQueryFilter(filter);

2
投票

对于那些希望在 EF Core 3.0 中实现 Ivan 的答案的人,请注意最后一行中的必要更改:

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
    var isActiveProperty = entityType.FindProperty("IsActive");
    if (isActiveProperty != null && isActiveProperty.ClrType == typeof(bool))
    {
        var parameter = Expression.Parameter(entityType.ClrType, "p");
        var filter = Expression.Lambda(Expression.Property(parameter, isActiveProperty.PropertyInfo), parameter);
        MutableEntityTypeExtensions.SetQueryFilter(entityType, filter);
    }
}

1
投票

这里是 EF Core 版本 6 的扩展方法

  public static void ApplySoftDeleteQueryFilter(this ModelBuilder modelBuilder)
  {
    var entityTypes = modelBuilder.Model
    .GetEntityTypes();

    foreach (var entityType in entityTypes)
    {
      var isActiveProperty = entityType.FindProperty("IsActive");
      if (isActiveProperty != null && isActiveProperty.ClrType == typeof(bool))
      {
        var entityBuilder = modelBuilder.Entity(entityType.ClrType);
        var parameter = Expression.Parameter(entityType.ClrType, "e");
        var methodInfo = typeof(EF).GetMethod(nameof(EF.Property))!.MakeGenericMethod(typeof(bool))!;
        var efPropertyCall = Expression.Call(null, methodInfo, parameter, Expression.Constant("IsActive"));
        var body = Expression.MakeBinary(ExpressionType.Equal, efPropertyCall, Expression.Constant(true));
        var expression = Expression.Lambda(body, parameter);
        entityBuilder.HasQueryFilter(expression);
      }
    }
  }

0
投票

在 .Net 7 中这有效。

对于所有实体;

看起来 IsActive=true 且 IsDeleted=false。

var entityTypes = builder.Model.GetEntityTypes();

        foreach (var entityType in entityTypes)
        {
            var isActiveProperty = entityType.FindProperty("IsActive");
            if (isActiveProperty != null && isActiveProperty.ClrType == typeof(bool))
            {
                var entityBuilder = builder.Entity(entityType.ClrType);
                var parameter = Expression.Parameter(entityType.ClrType, "e");
                var methodInfo = typeof(EF).GetMethod(nameof(EF.Property))!.MakeGenericMethod(typeof(bool))!;
                var efPropertyCall = Expression.Call(null, methodInfo, parameter, Expression.Constant("IsActive"));
                var body = Expression.MakeBinary(ExpressionType.Equal, efPropertyCall, Expression.Constant(true));
                var expression = Expression.Lambda(body, parameter);
                entityBuilder.HasQueryFilter(expression);
            }

            var isDeleteProperty = entityType.FindProperty("IsDeleted");
            if (isDeleteProperty != null && isDeleteProperty.ClrType == typeof(bool))
            {
                var entityBuilder = builder.Entity(entityType.ClrType);
                var parameter = Expression.Parameter(entityType.ClrType, "e");
                var methodInfo = typeof(EF).GetMethod(nameof(EF.Property))!.MakeGenericMethod(typeof(bool))!;
                var efPropertyCall = Expression.Call(null, methodInfo, parameter, Expression.Constant("IsDeleted"));
                var body = Expression.MakeBinary(ExpressionType.Equal, efPropertyCall, Expression.Constant(false));
                var expression = Expression.Lambda(body, parameter);
                entityBuilder.HasQueryFilter(expression);
            }
        }
© www.soinside.com 2019 - 2024. All rights reserved.