C# 对所有实体使用全局查询筛选器

C# 对所有实体使用全局查询筛选器,c#,entity-framework,global-query-filter,C#,Entity Framework,Global Query Filter,我最近发现了全局过滤器,这很好,因为我的任务是在我的应用程序中实现软删除。 目前我已经做到了: // Query filters https://docs.microsoft.com/en-us/ef/core/querying/filters modelBuilder.Entity<Address>().HasQueryFilter(m => !m.Deleted); modelBuilder.Entity<Attribute>().HasQueryFilter(

我最近发现了全局过滤器,这很好,因为我的任务是在我的应用程序中实现软删除。 目前我已经做到了:

// Query filters https://docs.microsoft.com/en-us/ef/core/querying/filters
modelBuilder.Entity<Address>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<Attribute>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<Brand>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<BrandAddress>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<BrandCategory>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<Category>().HasQueryFilter(m => !m.Deleted);
// many more entity types....
是否可以为继承
BaseModel
的任何类添加查询筛选器? 比如:

modelBuilder.Entity<BaseModel>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity().HasQueryFilter(m=>!m.Deleted);

因此,我不会忘记(以后)为我添加的模型添加查询过滤器?

对于最新的EF Core版本(应该也适用于3.0,对于早期版本,表达式替换应该手动处理,请参见
ReplacingExpressionVisitor
call),您可以使用一些(最少的量)自动执行,在您的
OnModelCreating
方法中。像这样的方法应该会奏效:

// define your filter expression tree
Expression<Func<BaseModel, bool>> filterExpr = bm => !bm.Deleted;
foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes())
{
    // check if current entity type is child of BaseModel
    if (mutableEntityType.ClrType.IsAssignableTo(typeof(BaseModel)))
    {
        // modify expression to handle correct child type
        var parameter = Expression.Parameter(mutableEntityType.ClrType);
        var body = ReplacingExpressionVisitor.Replace(filterExpr.Parameters.First(), parameter, filterExpr.Body);
        var lambdaExpression = Expression.Lambda(body, parameter);

        // set filter
        mutableEntityType.SetQueryFilter(lambdaExpression);
    }
}
//定义过滤器表达式树
表达式filterExpr=bm=>!bm.删除;
foreach(modelBuilder.Model.GetEntityTypes()中的变量mutableEntityType)
{
//检查当前实体类型是否为BaseModel的子级
if(mutableEntityType.ClrType.IsAssignableTo(typeof(BaseModel)))
{
//修改表达式以处理正确的子类型
var parameter=Expression.parameter(mutableEntityType.ClrType);
var body=ReplacingExpressionVisitor.Replace(filterExpr.Parameters.First(),参数,filterExpr.body);
var lambdaExpression=Expression.Lambda(主体,参数);
//设置过滤器
SetQueryFilter(lambdaExpression);
}
}

Yes,使用reflection搜索BaseModel的所有非抽象子类,然后在循环中为每个子类调用构造的泛型方法,同时检查此chlid类是否由模型生成器管理(否则不是construct也不是call)。Yes应该认为
IsAssignableTo
来自autofac?我将其更改为IsAssignableFrom并进行编译,但它似乎不起作用(因为我所有的单元测试现在都失败了)@r3plica不,它来自,它是在.NET 5中引入的。如果希望/需要将其更改为
IsAssignableFrom
,则需要更改If条件中的“顺序”:
typeof(BaseModel)。IsAssignableFrom(mutableEntityType.ClrType)
Ok;当我像您一样使用它时,它会抱怨
'Type'不包含'IsAssignableTo'的定义,并且找不到可访问的扩展方法'IsAssignableTo'接受类型为'Type'的第一个参数(您是否缺少using指令或程序集引用?
但是使用来自works的IsAssignableTo:)
如果(!typeof(BaseModel).IsAssignableFrom(mutableEntityType.ClrType))继续
// define your filter expression tree
Expression<Func<BaseModel, bool>> filterExpr = bm => !bm.Deleted;
foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes())
{
    // check if current entity type is child of BaseModel
    if (mutableEntityType.ClrType.IsAssignableTo(typeof(BaseModel)))
    {
        // modify expression to handle correct child type
        var parameter = Expression.Parameter(mutableEntityType.ClrType);
        var body = ReplacingExpressionVisitor.Replace(filterExpr.Parameters.First(), parameter, filterExpr.Body);
        var lambdaExpression = Expression.Lambda(body, parameter);

        // set filter
        mutableEntityType.SetQueryFilter(lambdaExpression);
    }
}