Простой условный запрос LINQ в Entity Framework 4
Недавно я перенес этот код в Entity Framework 4, и он не работает. Очевидно, если статус не имеет значения, верните все совпадения, если он имеет значение, соответствующее значению user.StatusID == 1
.
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
(!status.HasValue || user.StatusID == 1)
);
Возвращено исключение:
ArgumentException: The specified value is not an instance of type 'Edm.Int32'
Parameter name: value
Однако, удалив условный тест, и он отлично работает:
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
user.StatusID == 1
);
Любые идеи? Как вы выполняете условное тестирование в EF 4? Разумеется, не разделяются ли строки?
Я использую эти условные тесты снова и снова в Linq to Sql; это действительно странно, почему это не работает в EF 4. Должно быть что-то простое не так, возможно, есть рекомендуемый альтернативный способ делать что-то в EF 4.0.
Спасибо за помощь, ребята,
Graham
Ответы
Ответ 1
Хорошо, я решил это с помощью комбинации двух вещей.
- Выполнение простого нулевого теста.
- Тестирование локальной переменной cast
status
без метода .Value
.
Оба должны быть на месте, иначе он будет продолжать сбой с ошибкой! Было бы неплохо проверить свойство value, но я думаю, что запрос должен быть очень простым - довольно интересно!
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
(status == null || user.StatusID == (int) status)
);
Я буду ждать какой-либо лучшей реализации, иначе принимаю мой собственный ответ. Но спасибо за помощь всем.
Ответ 2
Как создать отдельную переменную для !status.HasValue
и использовать ее вместо этого в запросе?
Я думаю, проблема здесь в том, что EF пытается передать вашу переменную статуса в качестве параметра в запрос, а затем выполнить логику в самом SQL. Попробуйте проверить, какой SQL создан.
Ответ 3
Альтернативный способ выполнения нулевой проверки в предложении where будет разделять необязательный параметр и применять его только при необходимости.
например.
var data = users.Where(
user =>
user.Username == username &&
user.EncryptedPassword == password
);
if (status.HasValue)
{
data = data.Where(user => user.StatusID == status.Value);
}
return data.FirstOrDefault();
Я не думаю, что он будет предлагать многое по сравнению с вашим текущим решением, отличным от немного большей удобочитаемости.
Ответ 4
Похоже, вы уже нашли решение...
Однако, просто fyi... у меня нет проблем со следующей строкой в VS 2010
Nullable<int> status = 0;
String username = "Alexandre 2";
var test = _context.Contacts.SingleOrDefault(c => c.FirstName == username && (!status.HasValue || c.ContactID == 1));
Я не получаю никаких ошибок, и объект Contact, который я ожидаю, является возвратом... так что, если что-нибудь, это заставляет меня задаться вопросом, какой тип вашего поля user.StatusID?
Желаем удачи.
Ответ 5
что такое status.HasValue
? если статус является полем User
, вы должны называть его следующим образом: user.status.HasValue
просто выполните это:
if(status.HasValue)
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
user.StatusID == 1
);
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password
);
Ответ 6
Я думаю, вы должны заключить user.StatusID == 1 в дополнительный набор круглых скобок, так как я думаю, что в настоящее время EF пытается применить || операции с status.HasValue и user.StatusId, а затем сравнить результат с 1.
Ответ 7
На первой галансе это выглядит так:
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
(status == null || user.StatusID == 1)
);
но когда я смотрю на него больше, я чувствую, что это неправильно, а что?
return users.SingleOrDefault(
user =>
user.Username == username &&
user.EncryptedPassword == password &&
status != null &&
user.StatusID == 1)
);
Какова именно бизнес-логика?