EF Core HasQueryFilter работает только для первого значения в выражении фильтра - PullRequest
0 голосов
/ 22 февраля 2019

Я использую метод расширения EF Core HasQueryFilter, который находится внутри метода OnModelCreating.

Я внедряю идентификатор пользователя в DbContext с помощью службы, а затем применяю userId к фильтру запросов.Впервые при выполнении OnModelCreating он работает нормально, как и ожидалось.Но когда я меняю пользователя и передаю другой идентификатор пользователя в DbContext, фильтр запросов не проявляет такой очевидности, поскольку OnModelCreating на этот раз не вызывается.

Небольшой фон приложения: это основной API-проект 2.2.который аутентифицирует пользователей, используя токен JWT.Я заполняю заявки пользователей и инициализирую внедренную службу аутентификации, используя JWT, поэтому для каждого вызова API userId может отличаться, поэтому фильтр запросов должен работать с разными userIds.

Примеры кодов ниже:

public class SqlContext : DbContext
{
    private readonly IAuthService _authService;

    public SqlContext(DbContextOptions options, IAuthService authService) : base(options)
    {
        _authService = authService;
    }

    public DbSet<Device> Devices { get; set; }

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

        modelBuilder.Entity<Device>().HasQueryFilter(p => !p.IsDeleted && p.ManufacturerId == _authService.ManufacturerId);
    }
}

Как инициализируется DbContext.

 services.AddDbContextPool<TContext>(o =>
            o.UseSqlServer(configuration["Settings:SqlServer:DefaultConnection"],
                b =>
                {
                    b.MigrationsAssembly(configuration["Settings:SqlServer:MigrationAssembly"]);
                    b.CommandTimeout(60);
                    b.EnableRetryOnFailure(2);
                })
            .ConfigureWarnings(warnings =>
            {
                warnings.Throw(RelationalEventId.QueryClientEvaluationWarning);
            }))
            .AddTransient<TContext>();

1 Ответ

0 голосов
/ 25 февраля 2019

Наконец-то решил.

Поскольку фильтр работал, но он не обновлялся после создания модели после первого запроса.Причина в том, что EF кеширует созданную модель.Итак, мне пришлось реализовать IModelCacheKeyFactory , чтобы захватить различные модели в соответствии с фильтрами.

internal class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
{
    public object Create(DbContext context)
    {
        if (context is SqlContext dynamicContext)
        {
            return (context.GetType(), dynamicContext._roleCategory);
        }
        return context.GetType();
    }
}

И прикрепить его к контексту следующим образом.

protected override void OnConfiguring(DbContextOptionsBuilder builder)
    {
        base.OnConfiguring(builder);

        builder.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
    }
...