Динамическая фильтрация прерываний Entity Framework Plus метод поиска - PullRequest
0 голосов
/ 04 июня 2018

Мне нужно динамически фильтровать данные из конкретной таблицы в зависимости от прав пользователя.Например, «обычный» пользователь может видеть только назначенные ему записи, а администратор может видеть все.Я использую ninject для создания контекста БД для каждого запроса и создания контекста, передавая дополнительную информацию о пользователе в конструктор.Затем я применяю динамическую фильтрацию (EF6) из расширений EntityFramework-Plus:

public MyDbContext(bool isAdmin, string userId) : this()
{
    if (!isAdmin)
    {
        this.Filter<MyTable>(table => table.Where(...));
    }
}

Это решение работает, как и ожидалось, то есть вызывает такие методы, как:

ctx.MyTable.Where(...)

Результатом является дополнительное объединение, объявленное в фильтре.

Но странно себя ведет, когда я использую метод Find ().Я использую профилировщик SqlServer, чтобы увидеть, что происходит внутри:

  1. Я создаю контекст как ограниченный (не администратор) - вызов Find () приведет к дополнительному оператору WHERE, соответствующему лямбда-выражению фильтра
  2. Затем я создаю контекст как администратор (отдельный запрос) - вызов Find () приведет к тому же самому выражению SQL (я не ожидаю никаких дополнительных предложений SQL).

AFAIK это как-то связано с кэшированием запросов, так как добавление дополнительной строки в конструктор, похоже, решает проблему:

public MyDbContext(bool isAdmin, string userId) : this()
{
    // this "solves" the problem
    QueryFilterManager.ClearQueryCache(this);

    if (!isAdmin)
    {
        this.Filter<MyTable>(table => table.Where(...));
    }
}

Это выглядит как большое перерасход, и это не такприблизь меня к пониманию проблемы.Итак, вот мои вопросы:

  1. Почему эта проблема не влияет на Where (), но влияет на Find ()?
  2. Есть ли более чистый способ решения этой проблемы?Я читал о библиотеке динамических фильтров, но она мне не подходит, так как она работает только в модели с первым кодом (сначала БД здесь).
  3. Существуют ли более эффективные концепции фильтрации данных на основе данных по запросу (например, userId)в моем примере)?

ОБНОВЛЕНИЕ

Вот как выглядит мое лямбда-выражение:

private Func<IQueryable<MyTable>, IQueryable<MyTable>> GetFilter(string userId)
    {
        return t => t
                .Where(c.DataScopes.Any(
                        x => x.AspNetGroups.Any(
                            ang => ang.AspNetUsers.Any(
                                anu => anu.Id == userId))));
    }

AspNetGroups - моя пользовательская таблица для группировки пользователей.Данные разрешения назначаются группе пользователей.

...