Home > front end >  How can I make a dynamic query filter in entity framework core?
How can I make a dynamic query filter in entity framework core?

Time:01-03

I'm using dotnet 6, and I want to make a global query filter in ef core to check my authentication ID dynamically, but the OnModelCreating runs just once in the lifecycle of ASP.net. Do you have any ideas how to do this?

This is my OnModelCreating method. DeletedAt type is DateTime? and my authentication ID is CompanyId. I get _companyId from the constructor and the type of it is long?. When a request is triggered, this ID fills, but my idea's problem is this method called at the startup of the project! At that time, the _companyId is null and never called again!

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);
}

This is my ApplyQueryFilters method if you need:

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));
    }
}

I think I need a new idea to resolve this issue.

CodePudding user response:

OnModelCreating is cashed in first time, it's not running again I assume.

CodePudding user response:

Add the companyId to your Db Context then initialize it when you create the DbContext or when authenticate (you should have a DbContext peer session) :

public class ApplicationDbContext
{
    ...

    public long? _companyId ; 
}

in your OnModelCreating add this default filter (adapt it to your case) :

modelBuilder.Entity<YourEntity>().HasQueryFilter(b => EF.Property<string>(b, "companyId") == _companyId );

change the _companyId when needed.

  • Related