EF Core 8 – более эффективный способ закодировать это? Что-то вроде оператора SQL Case?

Код:

var primeCtr = con.Contractors?.Where(ctr => ctr.Type == "Prime").FirstOrDefault();
if (primeCtr == null)
   primeCtr = con.Contractors?.Where(ctr => ctr.Type == "Original Prime").FirstOrDefault();

Объяснение: Если существует подрядчик типа «Прайм», используйте его, иначе используйте «Оригинальный Прайм».

Я мог бы закодировать это, используя ? : выражение, но мне кажется, оно было бы менее эффективно?

var primeCtr = con.Contractors?.Where(ctr => ctr.Type == "Prime").Any() ? con.Contractors?.Where(ctr => ctr.Type == "Prime").FirstOrDefault() : con.Contractors?.Where(ctr => ctr.Type == "Original Prime").FirstOrDefault();

Я думаю, запрос «Prime» будет выполнен дважды?

Просто пытаюсь определить, есть ли более элегантный способ выразить это с помощью EF Core 8? Это мое первое приложение EF Core, и я не использовал старую версию EF уже несколько лет, поэтому она могла заржаветь.

Я не верю, что какой-либо из вариантов OrderBy будет эффективным, то, что у вас есть, имеет хорошую производительность, хотя и неудобно, если предположить, что индекс Type

Charlieface 21.08.2024 03:34
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
1
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Самый распространенный способ сделать это — заказать по предпочтениям и выбрать первый:

con.Contractors.OrderByDescending(ctr => ctr.Type == "Prime").FirstOrDefault()

Если типов больше, вам придется отфильтровать «Прайм» и «Оригинальный Прайм» (добавьте Where перед заказом).

Порядок нисходящий, потому что тогда тот, где ctr.Type == "Prime" является истинным, всплывает наверх.

Примечание: если con является экземпляром контекста, con.Contractors никогда не имеет значения null и вам не нужен оператор ?.

Gert Arnold 20.08.2024 22:55

Это интересная идея. ЕСТЬ еще типы, но они предварительно фильтруются перед этой логикой. Мне нравится этот ответ, но мне любопытно, каково влияние sql.

jrichview 22.08.2024 00:42

Вы можете использовать тернарный оператор внутри Where/OrderBy:

var primeCtr = con.Contractors.OrderBy(ctr => ctr.Type == "Prime" 
    ? 1 
    : ctr.Type == "Original Prime" ? 2
    : 3).FirstOrDefault();

Это преобразуется в CASE в SQL: (Не обращайте внимания на имена таблиц/столбцов, это был всего лишь быстрый тест с использованием предыдущей таблицы/объекта)

SELECT [p].[ProjectId], [p].[Name], [p].[Term1], [p].[Term2], [p].[Term3], [p].[TestDateTime]
FROM [Projects] AS [p]
ORDER BY CASE
    WHEN [p].[Term1] = N'orange' THEN 1
    WHEN [p].[Term1] = N'apple' THEN 2
    ELSE 3
END

Вы можете добавить столько значений, сколько необходимо, и даете полный контроль над порядком, не предполагая ни возрастающего, ни убывающего порядка значения типа.

Я мог бы поклясться, что тройка в этом выражении не подойдет. Но это может быть я неправильно помню или старая версия EF. Отлично, потому что именно так я бы сделал это в SQL.

jrichview 22.08.2024 00:44

Просто пытаюсь определить, есть ли более элегантный способ выразить это с помощью EF Core 8?

Возможно, не существует «хорошего» способа выразить это в SQL, но есть варианты, если вы хотите сэкономить на обходах, вы можете сделать что-то вроде следующего:

var primeCtr = con.Contractors
    .Where(ctr => new []{"Prime", "Original Prime"}.Contains(ctr.Type))
    .OrderByDescending(ctr => ctr.Type)
    .FirstOrDefault();

Ключевым моментом здесь является порядок: в результате Prime окажется сверху, если таковой имеется.

Чтобы включить больше типов, вы можете использовать тернарный оператор:

var primeCtr = con.Contractors
    .Where(ctr => new []{"Prime", "Original Prime", ...}.Contains(ctr.Type))
    .OrderBy(ctr => ctr.Type == "Prime" 
         ? 0
         : ctr.Type == "Original Prime"
             ? 1
             : ....)
    .FirstOrDefault();

В sql оператор CASE WHEN будет работать хорошо

jrichview 22.08.2024 00:41

Другие вопросы по теме