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); }
但是,我在if条件中得到NotSupportedException 。
错误消息是: 无法创建类型为“Closure type”的常量值。 在此上下文中仅支持基本类型(例如Int32,String和Guid’)。
请注意, pCategory是Enum类型。
编辑 :根据您的更新,错误可能与您的实体类中的枚举有关。 有关更多信息和解决方法,请参阅此博客条目 。 我将原始答案作为对查询语法的改进。
尝试使用FirstOrDefault在查询本身中选择第一个实体,然后检查结果是否为null。
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的方法,任何返回任何内容的方法都可以选择。
如果您有名为“Select”和“Where”的实例方法返回单个对象或扩展特定于您的类的方法并返回单个对象,则将使用这些方法而不是标准的linq。
我的猜测是,在您的类中定义的“选择”或“在哪里”方法使linq返回单个值而不是IEnumerable
。
我不知道根据查询结果会创建不同的匿名对象。 我猜他们只是希望结果是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(); } ... }
你需要明确地将类转换为astring进行比较。
所以我通常这样做
var myClassAStr = myClassA.ToString(); var x = (from a in entites where a.ValToCompare == myClassAStr select a).first(); // do stuff with x ...
尝试使用
IENumerable results = from r in entities.MachineRevision ...
代替。
我认为它导致了你的问题。
编辑:
阅读错误消息。 “无法创建类型’闭包类型’的常量值。在此上下文中仅支持基本类型(例如Int32,String和Guid’)。”
其中一个比较是使用非int,string或guid的类型。 我在猜这个类别。
r.Machine.IdMachine == pIdMachine && r.Category == pCategory
有趣的是,LinqToSql将允许这种构造。 不知道为什么LinqToEntities不支持这个。
我想你也可以通过使用lambda表达式选择你想要的另一种更简单的方法。
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); }
然后像往常一样继续