如何在Entity Framework Core中创建一个动态查询过滤器?

3

我正在使用 dotnet 6,并且想要在 ef core 中创建一个全局查询过滤器,以动态检查我的身份验证 ID,但是 OnModelCreating 只在 ASP.net 的生命周期中运行一次。你有什么好的想法吗?

这是我的 OnModelCreating 方法。 DeletedAt 类型是 DateTime?,我的身份验证 ID 是 CompanyId。 我从构造函数中获取 _companyId,其类型为 long?。当触发请求时,此 ID 填充,但我的想法的问题是此方法在项目启动时调用!那时,_companyId 为空,永远不会再次调用!

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.ApplyQueryFilters<IDeletedAt>(x => x.DeletedAt == null);
    modelBuilder.ApplyQueryFilters<IDeletedAtAndCompany>(x => x.DeletedAt == null && x.CompanyId == _companyId);
}

这是我的ApplyQueryFilters方法,如果你需要:

public static void ApplyQueryFilters<T>(this ModelBuilder modelBuilder, Expression<Func<T, bool>> expression)
{
    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        if (entityType.ClrType.GetInterface(typeof(T).Name) == null) continue;
        var newParam = Expression.Parameter(entityType.ClrType);
        var newBody = ReplacingExpressionVisitor
            .Replace(expression.Parameters.Single(), newParam, expression.Body);

        modelBuilder.Entity(entityType.ClrType).HasQueryFilter(Expression.Lambda(newBody, newParam));
    }
}

我觉得我需要一个新的想法来解决这个问题。


什么是问题?在查询执行之前分配“_companyId”,EF Core应该使用新参数。 - Svyatoslav Danyliv
1个回答

0

将companyId添加到您的Db Context中,然后在创建DbContext或进行身份验证时进行初始化(您应该有一个DbContext对等会话):

public class ApplicationDbContext
{
    ...

    public long? _companyId ; 
}

在您的 OnModelCreating 中添加此默认筛选器(根据您的情况进行调整):
modelBuilder.Entity<YourEntity>().HasQueryFilter(b => EF.Property<string>(b, "companyId") == _companyId );

根据需要更改_companyId。


如果有两个并发请求,它会如何表现? - Guru Stron
所有身份验证后的查询都将使用公司过滤器,无论是否并发。 - Mourad GHERSA
1
这样做不行。如果使用静态变量,当并发请求发生时,您将得到错误的公司 ID。 - davidfowl
正确的静态是全局的,您应该将属性添加到对等会话DbContext中。 - Mourad GHERSA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接