Gup*_*R4c 6 c# entity-framework-core ef-core-3.1
根据全局查询过滤器文档,我们不能对一个实体使用多个查询过滤器,我们只能有一个,其中包含多个条件:
目前无法在同一实体上定义多个查询过滤器 - 仅应用最后一个。但是,您可以使用逻辑 AND 运算符(C# 中的 &&)定义具有多个条件的单个过滤器。
因此,在我正在使用 EF Core 3.1 的项目中,我尝试这样做。在我的查询过滤器中,我尝试应用 a 的条件TenantId和 的条件IsDeleted:
internal Expression<Func<TEntity, bool>> QueryFilters<TEntity>()
where TEntity : class {
return _ => (TenantId.HasValue
&& _ is ITenantableEntity
&& ((ITenantableEntity)_).TenantId == new TenantId(TenantId.Value)
|| true)
&& (_ is IDeletableEntity
&& !((IDeletableEntity)_).IsDeleted
|| true);
}
Run Code Online (Sandbox Code Playgroud)
被TenantId定义为 的属性DbContext:
internal int? TenantId => _identity.TenantId;
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,在某些情况下,例如 Hangfire 后台作业,TenantId将始终为空。我以为我是在上述情况下防范的,但是当我尝试时,生成了以下查询参数:
queryContext.AddParameter(
name: "__ef_filter__HasValue_0",
value: (object)Invoke(queryContext => Convert(Convert(queryContext.Context, DbContext).TenantId.HasValue, Object), queryContext)
);
queryContext.AddParameter(
name: "__ef_filter__p_1",
value: (object)Invoke(queryContext => Convert(Convert(new TenantId(Convert(queryContext.Context, DbContext).TenantId.Value), Nullable`1), Object), queryContext)
);
Run Code Online (Sandbox Code Playgroud)
由于这些参数,NRE 导致查询崩溃。是否有更好或更合适的方法来在查询过滤器中构建表达式,以便如果确实TenantId有值,则生成参数,而不是在没有嵌套条件的情况下生成参数?
为了使后台作业中的查询成功,我必须使用IgnoreQueryFilters(),它修复了TenantId检查,但现在也忽略了IsDeleted我想继续进行的检查。
我认为你的问题不在于如何处理全局过滤器查询,而在于如何执行后台作业。
TenantId 和依赖于登录用户的任何其他信息将不可用于hangfire 作业。
您可以通过将适当的参数传递给后台作业来轻松解决这个问题,这样hangfire将在数据库中序列化它并在运行时反序列化它。
private long currentTenantId = loggedUser.GetTenantId(); // or any other way to get the tenantId when the background job was scheduled.
BackgroundJob.Enqueue<ISomeService>(s => s.SomeFunction(currentTenantId));
Run Code Online (Sandbox Code Playgroud)
如果您查看hangfireJob表,您会注意到InvocationData和Arguments列将保存运行所需的所有信息SomeFunction()。