Linq возвращает список или отдельный объект - PullRequest
7 голосов
/ 30 декабря 2008

У меня есть запрос Linq to Entities, подобный этому:

var results = from r in entities.MachineRevision
              where r.Machine.IdMachine == pIdMachine
                 && r.Category == (int)pCategory
              select r;

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

if (results.Count() > 0)
{
    return new oMachineRevision(results.First().IdMachineRevision);
}

Однако я получаю NotSupportedException в , если условие.

Сообщение об ошибке: Невозможно создать постоянное значение типа 'Тип закрытия'. В этом контексте поддерживаются только примитивные типы (такие как Int32, String и Guid).

Обратите внимание, что pCategory является типом Enum.

Ответы [ 8 ]

11 голосов
/ 30 декабря 2008

РЕДАКТИРОВАТЬ : В зависимости от вашего обновления ошибка может быть связана с перечислением в вашем классе сущностей. См. Эту запись в блоге для получения дополнительной информации и обходного пути. Я оставляю свой первоначальный ответ как улучшение синтаксиса вашего запроса.

Попробуйте выполнить выбор первого объекта в самом запросе, используя FirstOrDefault, а затем проверьте, равен ли результат нулю.

int compareCategory = (int)pCategory; // just a guess
var result = (from r in entities.MachineRevision
              where r.Machine.IdMachine == pIdMachine
                 && r.Category == compareCategory
              select r).FirstOrDefault();

if (result != null)
{
     return new oMachineRevision(result.IdMachineRevision);
}
2 голосов
/ 30 декабря 2008

В стандартной реализации linq операторы "select" и "where" отображаются на методы, которые возвращают IEnumerable или IQueryable. Поэтому стандартные методы linq при использовании всегда должны возвращать IEnumerable из вашего запроса, а не один объект.

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

В случае, если у вас есть методы экземпляра с именами «Выбор» и «Где», которые возвращают один объект или методы расширений, специфичные для вашего класса, и возвращают один объект, который будет использоваться вместо стандартных linq.

Я предполагаю, что метод "Select" или "Where", определенный в вашем классе, заставляет linq возвращать одно значение вместо IEnumerable<T>.

2 голосов
/ 30 декабря 2008

Почему бы просто не использовать FirstOrDefault () вместо этого и проверять на ноль? Я не вижу выгоды в том, чтобы запросить счет и затем взять первый элемент.

1 голос
/ 29 ноября 2011

Это относится и ко всем неявным типам. Я должен признать, что я все время забываю об этом, и вот как я наткнулся на этот пост.

если у вас есть

class ClassA {
               ...

               private string value;

               ...

               public static implicit operator string(ClassA value)
               {
                    return value.ToString();
               } 

              ...
}

вам нужно явно привести класс к астрине для сравнения.

поэтому я обычно делаю это

    var myClassAStr = myClassA.ToString();

    var x = (from a in entites where a.ValToCompare == myClassAStr select a).first();

// do stuff with x
    ...
1 голос
/ 30 декабря 2008

Я не знал, что разные анонимные объекты будут создаваться в зависимости от результата запроса. Я думаю, они просто хотели, чтобы результаты имели тип IEnumerable

Как насчет использования foreach?

var results = from r in entities.MachineRevision
              where r.Machine.IdMachine == pIdMachine
                 && r.Category == pCategory
              select r;

foreach( var r in results )
{
    yield return new oMachineRevision( r.IdMachineRevision );
}
0 голосов
/ 16 июня 2009

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

var result = entities.MachineRevision
                 .Where(x => x.Machine.IdMachine == pIdMachine)
                 .Where(y => y.Category == (int)pCategory)
                 .FirstOrDefault();

if (result != null)
{
     return new oMachineRevision(result.IdMachineRevision);
}

и затем, как обычно

0 голосов
/ 30 декабря 2008

Edit:

Прочтите сообщение об ошибке. «Невозможно создать постоянное значение типа« тип закрытия ». В этом контексте поддерживаются только примитивные типы (такие как Int32, String и Guid». »

Одно из этих сравнений относится к типу, который не является int, string или guid. Я угадываю категорию.

r.Machine.IdMachine == pIdMachine && r.Category == pCategory

Интересно, что LinqToSql разрешит эту конструкцию. Не знаю, почему LinqToEntities не поддерживает это.

0 голосов
/ 30 декабря 2008

попробуйте использовать

IENumerable<MachineRevision> results = from r in entities.MachineRevision
...

вместо.

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

...