Как сделать фильтры условных запросов в EF Core? - PullRequest
0 голосов
/ 29 апреля 2020

Согласно документации Global Query Filters мы не можем использовать несколько фильтров запросов для объекта, у нас может быть только один, с несколькими условиями в нем:

В настоящее время невозможно определить несколько фильтров запросов для одной и той же сущности - будет применен только последний. Однако вы можете определить один фильтр с несколькими условиями, используя логический оператор AND (&& в C#).

Итак, в проекте, над которым я работаю с EF Core 3.1 Я пытался сделать это. В моем фильтре запросов я пытаюсь применить условие для 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);
}

TenantId определяется как свойство для DbContext:

internal int? TenantId => _identity.TenantId;

Проблема, с которой я сталкиваюсь, заключается в том, что в некоторых сценариях ios, таких как фоновые задания 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)
);

И из-за этих параметров запросы просто терпят крах с NRE. Есть ли лучший или более подходящий способ построения выражения в фильтре запросов, чтобы, если TenantId действительно имел значение, генерировался параметр, а не иначе, как у меня есть вложенное условное выражение?

Чтобы успешно выполнить запрос в фоновом задании, я должен использовать IgnoreQueryFilters(), который исправляет проверку TenantId, но теперь также игнорирует проверку IsDeleted, которую я хотел бы продолжить иметь.

...