Простой условный запрос LINQ в Entity Framework 4 - PullRequest
10 голосов
/ 26 апреля 2011

Я недавно перенес этот код в 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

Ответы [ 7 ]

5 голосов
/ 26 апреля 2011

Хорошо, я решил это комбинацией двух вещей.

  1. Выполнение простого нулевого теста.
  2. Тестирование локального преобразования status переменная без метод .Value.

Оба должны быть на месте, иначе он будет продолжать сбой с ошибкой! Было бы неплохо проверить свойство value, но я думаю, что запрос должен быть очень простым - довольно интересным!

return users.SingleOrDefault(
                user =>
                user.Username == username &&
                user.EncryptedPassword == password &&
                (status == null || user.StatusID == (int) status)
                );

Я буду ждать любой лучшей реализации, иначе приму мой собственный ответ. Но спасибо всем за помощь.

2 голосов
/ 26 апреля 2011

Альтернативным способом выполнения нулевой проверки в предложении 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();

Не думаю, что оно будет намного лучше вашего текущего решения, кроме немного более читабельного.

2 голосов
/ 26 апреля 2011

Как насчет создания отдельной переменной для !status.HasValue и использования ее вместо этого в запросе?

Мне кажется, проблема в том, что EF пытается передать переменную состояния в качестве параметра в запрос, а затем выполнить логику вСам SQL.Попробуйте проверить, какой SQL генерируется.

1 голос
/ 26 апреля 2011

Похоже, вы уже нашли решение ...

Однако, к вашему сведению ... у меня нет проблем со следующей строкой в ​​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?

удачи

0 голосов
/ 26 апреля 2011

При первом взгляде в моем представлении это выглядит так:

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)
  );

Что именно за этим стоит бизнес-логика?

0 голосов
/ 26 апреля 2011

Я думаю, что вы должны заключить user.StatusID == 1 в дополнительный набор скобок, так как я думаю, что в настоящее время EF пытается применить || операция для status.HasValue и user.StatusId, а затем сравните результат с 1.

0 голосов
/ 26 апреля 2011

что такое 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
                );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...