Linq возвращает список или один объект
Вопрос
У меня есть запрос 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);
}
Однако я получаю Неподдерживаемое исключение в если состояние.
Сообщение об ошибке: Невозможно создать постоянное значение типа «Тип закрытия».В этом контексте поддерживаются только примитивные типы (такие как Int32, String и Guid).
Обратите внимание, что pКатегория является типом Enum.
Решение
РЕДАКТИРОВАТЬ:Судя по вашему обновлению, ошибка может быть связана с перечислением в вашем классе сущности.Видеть это запись в блоге для получения дополнительной информации и обходного пути.Я оставляю свой первоначальный ответ как улучшение синтаксиса вашего запроса.
Попробуйте выбрать первую сущность в самом запросе с помощью 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);
}
Другие советы
Почему бы просто не использовать FirstOrDefault() и проверить значение null?Я не вижу преимущества в запросе счетчика и последующем получении первого элемента.
В стандартной реализации linq операторы «select» и «where» соответствуют методам, возвращающим IEnumerable или IQueryable.Таким образом, стандартные методы linq при использовании всегда должны возвращать IEnumerable из вашего запроса, а не один объект.
Но методы linq, являющиеся кандидатами на роль операторов linq, не ограничиваются методами, возвращающими IEnumerables, можно выбрать любой метод, возвращающий что угодно.
Если у вас есть методы экземпляра с именами «Выбрать» и «Где», которые возвращают один объект, или методы расширения, специфичные для вашего класса и возвращающие один объект, они будут использоваться вместо стандартных методов linq.
Я предполагаю, что метод «Выбрать» или «Где», определенный в вашем классе, заставляет linq возвращать одно значение вместо IEnumerable<T>
.
Я не знал, что в зависимости от результата запроса будут создаваться разные анонимные объекты.Я думаю, они просто хотели, чтобы результаты имели тип 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 );
}
Это касается и всех неявных типов.Должен признаться, я все время об этом забывал, и именно поэтому наткнулся на этот пост.
если у вас есть
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
...
попробуйте использовать
IENumerable<MachineRevision> results = from r in entities.MachineRevision
...
вместо.
Я думаю, что ваша проблема вызвана var.
Редактировать:
Прочтите сообщение об ошибке.«Невозможно создать постоянное значение типа «Тип закрытия».В этом контексте поддерживаются только примитивные типы («такие как Int32, String и Guid»).
Одно из этих сравнений связано с типом, отличным от int, string или guid.Я предполагаю, что Категория.
r.Machine.IdMachine == pIdMachine && r.Category == pCategory
Интересно, что LinqToSql допускает такую конструкцию.Не знаю, почему LinqToEntities не поддерживает это.
Я думаю, вы также можете выбрать нужный элемент другим, более простым способом, используя лямбда-выражения.
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);
}
а затем действуйте, как обычно