У меня номера сотрудников в базе данных хранятся таким образом.
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, а затем вернуть результат. Любые предложения будут оценены.
Я использую Microsoft SQL
Какой тип employeeId?
тип идентификатора сотрудника — строка





Мне кажется, что вы подходите к этому не с той стороны. Даже если бы это сработало, имело бы смысл обрезать каждое значение в базе данных? Конечно, гораздо проще выяснить, как сотрудник будет отформатирован в базе данных, а затем провести прямое сравнение с этим, используя индексы базы данных и т. д.:
// 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, а некоторые нет.
Как насчет: .Where(e => e.EmployeeNumber == formattedEmployeeId || e.EmployeeNumber == идентификатор сотрудника) ?
Я подозреваю, что «номер» сотрудника подобен телефонному «номеру», т. е. представляет собой строку, обычно состоящую из цифр, в которой ведущие нули по-прежнему имеют значение. Так может быть, присвоение ему числового типа в базе данных — не такая уж хорошая идея?
@Anjali: Во-первых, это похоже на информацию, которая должна была быть в вопросе с самого начала. Во-вторых, идея WillC все еще должна работать. Я считаю, что это все же должно быть более эффективным вариантом, чем обрезка согласно первому подходу в ответе Гуру Строна.
@AndrewMorton: Это зависит от того, что подразумевается под словами «ведущие нули по-прежнему значимы». Если «E0003» и «E03» используются как разные идентификаторы, то да, это предотвратит использование числового типа... но я бы предположил, что это уже огромная проблема в дизайне.
Я думаю, мы все согласны с тем, что дизайн нуждается в улучшении :)
Попробуйте использовать перегрузку 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
Какую базу данных вы используете?