Linq返回列表或单个对象

时间:2008-12-30 11:53:35

标签: c# linq .net-3.5 enums

我有像这样的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 是枚举类型。

8 个答案:

答案 0 :(得分:11)

编辑:根据您的更新,错误可能与实体类中的枚举有关。有关详细信息和解决方法,请参阅此blog entry。我将原始答案作为对查询语法的改进。

尝试使用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);
}

答案 1 :(得分:2)

为什么不直接使用FirstOrDefault()并检查null?我无法看到查询计数然后获取第一个元素的好处。

答案 2 :(得分:2)

在linq的标准实现中,运算符“select”和“where”映射到返回IEnumerable或IQueryable的方法。因此,使用标准linq方法时,应始终从查询中返回IEnumerable而不是单个对象。

但linq运算符的linq方法不仅限于返回IEnumerables的方法,任何返回任何内容的方法都可以选择。

如果您有名为“Select”和“Where”的实例方法返回单个对象或扩展特定于您的类的方法并返回单个对象,那么将使用这些方法而不是标准的linq。

我的猜测是,类中定义的“选择”或“位置”方法会使linq返回单个值而不是IEnumerable<T>

答案 3 :(得分:1)

我不知道根据查询结果会创建不同的匿名对象。我猜他们只是希望结果是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 );
}

答案 4 :(得分:1)

这也适用于所有隐式类型。我必须承认我一直忘记这一点,这就是我遇到这篇文章的方式。

如果你有

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
    ...

答案 5 :(得分:0)

尝试使用

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

代替。

我认为它导致了你的问题。

答案 6 :(得分:0)

编辑:

阅读错误消息。 “无法创建类型'闭包类型'的常量值。在此上下文中仅支持基本类型(例如Int32,String和Guid')。”

其中一个比较是使用非int,string或guid的类型。我猜这个类别。

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

有趣的是,LinqToSql将允许这种构造。不知道为什么LinqToEntities不支持这个。

答案 7 :(得分:0)

我认为你也可以通过使用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);
}

然后按照正常情况继续进行