有什么方法可以将
HasQueryFilter()
全局应用到我的所有实体吗?我不想一一添加ModelBuilder
。
modelBuilder.Entity<Manufacturer>().HasQueryFilter(p => p.IsActive);
如果您有定义
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);
对于那些希望在 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);
}
}
这里是 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);
}
}
}
在 .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);
}
}