Размещение оператора обрезки в LINQ

У меня номера сотрудников в базе данных хранятся таким образом.

EmployeeNumber
E123456
E999999
E666666
E111111
444444

Некоторые значения начинаются с «E», а некоторые нет.

Я хочу написать оператор LINQ, чтобы сопоставить номер сотрудника базы данных с идентификатором сотрудника, переданным из Интернета. Я попробовал написать оператор LINQ следующим образом:

_akContext.EmployeeInfos.Where(e => e.EmployeeNumber.TrimStart('E') == employeeId).OrderBy(e => e.EmployeeInfoId).Select(e => e.EmployeeInfoId).ToList();

Используя приведенный выше оператор LINQ, я постоянно получаю сообщение об ошибке:

.Where(e => e.EmployeeNumber.TrimStart(E) == __TrimStart_0)' could not be translated

ниже скриншот:

Единственный способ, который я могу придумать, - это пройтись по базе данных и удалить все буквы "E", а затем сравнить номер сотрудника с идентификатором сотрудника, но это будет двухэтапный процесс. Мне было интересно, есть ли способ обрезать E в том же запросе LINQ, а затем вернуть результат. Любые предложения будут оценены.

Какую базу данных вы используете?

Guru Stron 12.04.2024 19:53

Я использую Microsoft SQL

Anjali 12.04.2024 19:57

Какой тип employeeId?

Guru Stron 12.04.2024 19:58

тип идентификатора сотрудника — строка

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

Ответы 3

Мне кажется, что вы подходите к этому не с той стороны. Даже если бы это сработало, имело бы смысл обрезать каждое значение в базе данных? Конечно, гораздо проще выяснить, как сотрудник будет отформатирован в базе данных, а затем провести прямое сравнение с этим, используя индексы базы данных и т. д.:

// Add any extra logic here such as padding.
var prefixedEmployeeId = $"E{employeeId}";
// Again, potentially apply zero-padding. The use
// of a separate variable name makes the purpose clearer.
var unprefixedEmployeeId = employeeId */;

var employees = _akContext.EmployeeInfos
    .Where(e => e.EmployeeNumber == prefixedEmployeeId ||
                e.EmployeeNumber == unprefixedEmployeeId)
    .OrderBy(e => e.EmployeeInfoId)
    .Select(e => e.EmployeeInfoId)
    .ToList();

Это может быть проблемой, если идентификаторы ваших сотрудников отформатированы в базе данных очень непоследовательно (например, некоторые используют E, некоторые используют EE, некоторые вообще не используют E), но я очень надеюсь, что это не так. Если это просто случай «некоторые с префиксом E» и «некоторые с префиксом E», то представление обоих в запросе должно быть в порядке - и я все равно утверждаю, что это лучше, чем обрезка. Хотя исправить базу данных, чтобы она была согласованной, определенно было бы лучше...

проблема в том, что в базе данных некоторые значения начинаются с E, а некоторые нет.

Anjali 12.04.2024 19:56

Как насчет: .Where(e => e.EmployeeNumber == formattedEmployeeId || e.EmployeeNumber == идентификатор сотрудника) ?

WillC 12.04.2024 20:06

Я подозреваю, что «номер» сотрудника подобен телефонному «номеру», т. е. представляет собой строку, обычно состоящую из цифр, в которой ведущие нули по-прежнему имеют значение. Так может быть, присвоение ему числового типа в базе данных — не такая уж хорошая идея?

Andrew Morton 12.04.2024 20:21

@Anjali: Во-первых, это похоже на информацию, которая должна была быть в вопросе с самого начала. Во-вторых, идея WillC все еще должна работать. Я считаю, что это все же должно быть более эффективным вариантом, чем обрезка согласно первому подходу в ответе Гуру Строна.

Jon Skeet 12.04.2024 20:55

@AndrewMorton: Это зависит от того, что подразумевается под словами «ведущие нули по-прежнему значимы». Если «E0003» и «E03» используются как разные идентификаторы, то да, это предотвратит использование числового типа... но я бы предположил, что это уже огромная проблема в дизайне.

Jon Skeet 12.04.2024 20:56

Я думаю, мы все согласны с тем, что дизайн нуждается в улучшении :)

Andrew Morton 12.04.2024 21:30
Ответ принят как подходящий

Попробуйте использовать перегрузку TrimStart, принимающую массив символов ( на основе исходного кода кажется, можно перевести):

_akContext.EmployeeInfos
    .Where(e => e.EmployeeNumber.TrimStart(new []{'E'}) == employeeId)

Хотя эта перегрузка не указана в Сопоставлениях функций поставщика Microsoft SQL Server.

Если это не сработает, вы можете попробовать обойти замену:

_akContext.EmployeeInfos
    .Where(e => e.EmployeeNumber.Replace("E", "") == employeeId)

Другие варианты включают создание вычисляемого столбца в базе данных, который будет содержать обрезанное значение или форматирование данных на стороне клиента (что, возможно, должно быть вариантом перехода в данном конкретном случае):

_akContext.EmployeeInfos
    .Where(e => e.EmployeeNumber == employeeId 
         || e.EmployeeNumber == ("E" + employeeId))

P.S.

Я настоятельно рекомендую нормализовать данные (т. е. удалить E из EmployeeNumber) в базе данных, если это возможно, или, может быть, стоит подумать о создании соответствующего индекса в обрезанной версии EmployeeNumber (зависит от моделей использования и размера данных).

Самый производительный и простой подход (уже упомянутый @guru-stron, но стоит выделить)

var employeeId2 = "E" + employeeId;

_akContext.EmployeeInfos
    .Where(e => e.EmployeeNumber == employeeId 
             || e.EmployeeNumber == employeeId2)
  • Вычислить вариант с префиксом локально один раз
  • Индекс кредитного плеча EmployeeNumber
  • Никаких накладных расходов на вычисляемый столбец и/или дополнительный индекс в БД.

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