Составление запроса OR с помощью EF Core

2

У меня есть DbQuery, который я пытаюсь отфильтровать на основе различных (необязательных) параметров, предоставленных пользователем. Я пытаюсь составить запрос с помощью LINQ, чтобы учесть это, но натолкнулся на загвоздку, так что это как бы два участника.

Postgres: я использую postgres, поэтому у меня есть столбец массива, и я хочу иметь возможность использовать useCaseArray && entity.useCases. Однако поставщик EF в настоящее время не поддерживает это.

Я не хочу переходить к составлению всего этого в raw sql, если я могу избежать этого, поэтому я подумал, что могу сделать очень уродливый ГДЕ, как это:

WHERE (useCases.Contains(x) || useCases.Contains(y) ...)

однако я не знаю, как составить это с помощью LINQ. Я знаю, что вы можете сделать оперативные операции, такие как

query.Where(item => item.cases.Contains(x) || item.cases.Contains(y))

Однако я не могу написать это так, потому что мне нужно использовать foreach/loop для массива, содержащего мои X и Y. Кто-нибудь знает, как я могу это сделать?

foreach(var usecase in request.UseCases) 
{
  query = query.Where(item => item.UseCases.Contains(usecase));
}

Это сгенерирует только длинный ряд AND, когда я хочу, чтобы все это подмножество было одним OR.

Я надеюсь, что мне удалось объяснить это соответствующим образом! С другой стороны, я хотел бы иметь возможность вставлять один компонент предложения WHERE в сырой SQL, но я думаю, что это приведет к взрыву EF Core, и звучит так, как если бы FromSQL не поддерживал WHERE просто SELECT.

ОБНОВИТЬ:

На основе комментариев я попробовал это: https://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/, который работает в основном фантастически:

var useCaseQuery = request.UseCases
  .Select(useCase => PredicateBuilder.Create<MyEntity>(entity => entity.UseCases.Contains(useCase)))
  .Aggregate(PredicateBuilder.Or);

query = query.Where(useCaseQuery);

В некотором смысле это здорово, но EF Core все еще не нравится:

The LINQ expression 'where ({[assumption].UseCases => Contains(__useCase_3)} OrElse {[assumption].UseCases => Contains(__useCase_4)})' could not be translated and will be evaluated locally.

Я думаю, что это будет хорошо для меня, но первоначальная проблема остается, я хотел бы, чтобы это работало на БД.

  • 1
    Любой помощник по построению предикатов будет выполнять работу ИЛИ - как этот , этот , даже классический и т. Д.
  • 1
    Derp. Я использовал один из них раньше, но я просто предположил, что по какой-то причине он не будет работать с ядром. Я попробую, спасибо.
Показать ещё 4 комментария
Теги:
entity-framework-core

1 ответ

1
Лучший ответ

Поэтому после некоторых полезных комментариев я попробовал FromSql

if (request.UseCases != null && request.UseCases.Count > 0)
{
  // I know UseCases is a List<int> hence why I'm just joining without escaping.
  query = query.FromSql("SELECT * FROM my_table WHERE ARRAY[" + String.Join(',', request.UseCases) + "] && use_cases");
}

Мне это не нравится на 100%, потому что теперь мой сервис знает о моих таблицах базы данных и именах полей, что в значительной степени сводит на нет цель ORM. Однако для этого конкретного случая он делает то, что мне нужно, и я могу продолжать сочинять так:

if (request.Groups != null && request.Groups.Count > 0)
{
  query = query.Where(data => request.Groups.Contains(data.GroupId));
}

if (!String.IsNullOrWhiteSpace(request.Title))
{
  query = query.Where(data => EF.Functions.ILike(data.Name, $"%{request.Title}%"));
}

SQL производится так:

SELECT my_table.classes, my_table."group", my_table.group_id, my_table.id, my_table.name, my_table.use_cases
FROM (
    SELECT * FROM my_table WHERE ARRAY[7,4] && use_cases
) AS assumption
WHERE my_table.group_id IN (7) AND (my_table.name ILIKE @__Format_3 ESCAPE '' = TRUE)
ORDER BY my_table.name DESC

Пока драйвер Postgres EF Core не будет обновлен, это может быть лучшим, что я могу сделать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню