Linq返回列表或单个对象

时间:2021-02-23 20:50:50

I have a Linq to Entities query like this one:

我有像这样的Linq to Entities查询:

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

Usually, I use the code below to check if some results are returned:

通常,我使用下面的代码来检查是否返回了一些结果:

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

However, I'm getting NotSupportedException in the if condition.

但是,我在if条件中得到NotSupportedException。

The error message is: Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

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

Note that pCategory is an Enum type.

请注意,pCategory是Enum类型。

8 个解决方案

#1


EDIT: Based on your update, the error may be related to an enum in your entity class. See this blog entry for more information and a work-around. I'm leaving my original answer as an improvement on your query syntax.

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

Try doing the selection of the first entity in the query itself using FirstOrDefault and then check if the result is null.

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

#2


Why not just use FirstOrDefault() instead, and check for null? I can't see the benefit in querying for the count and then taking the first element.

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

#3


In the standard implementation of linq, the operators "select" and "where" map to methods that return an IEnumerable or IQueryable. So standard linq methods when used should always return an IEnumerable from your query not a single object.

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

But linq methods that are candidates for the linq operators are not restricted to methods returning IEnumerables, any method returning anything can be chosen.

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

In case you have instance methods named "Select" and "Where" that return a single object or extensions methods that are specific to your class and return a single object those will be used instead of the standard linq ones.

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

My guess is that either a "Select" or "Where" method defined in your class is making linq return a single value instead of a IEnumerable<T>.

我的猜测是,在您的类中定义的“选择”或“在哪里”方法使linq返回单个值而不是IEnumerable

#4


I didn't know different anonymous objects would be created depending on the query result. I guess they just wanted results to be of type IEnumerable

我不知道根据查询结果会创建不同的匿名对象。我猜他们只是希望结果是IEnumerable类型

How about using a foreach?

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

#5


This goes for all implicit types too. I must admit I keep forgetting this and that's how I came across this post.

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

if you have

如果你有

class ClassA {
               ...

               private string value;

               ...

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

              ...
}

you need to explictly cast the class to astring for comparison.

你需要明确地将类转换为astring进行比较。

so I usually do this

所以我通常这样做

    var myClassAStr = myClassA.ToString();

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

// do stuff with x
    ...

#6


try using

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

instead.

I think its the var that's causing your issue.

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

#7


Edit:

Read the error message. "Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."

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

One of these comparisions is with a type that is not int, string or guid. I'm guessing the Category.

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

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

Interestingly, LinqToSql will allow this construction. Don't know why LinqToEntities does not support this.

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

#8


I think you could also select the item you want another, simpler way by using lambda expressions.

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

and then proceeding as you would normally

然后像往常一样继续

#1


EDIT: Based on your update, the error may be related to an enum in your entity class. See this blog entry for more information and a work-around. I'm leaving my original answer as an improvement on your query syntax.

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

Try doing the selection of the first entity in the query itself using FirstOrDefault and then check if the result is null.

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

#2


Why not just use FirstOrDefault() instead, and check for null? I can't see the benefit in querying for the count and then taking the first element.

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

#3


In the standard implementation of linq, the operators "select" and "where" map to methods that return an IEnumerable or IQueryable. So standard linq methods when used should always return an IEnumerable from your query not a single object.

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

But linq methods that are candidates for the linq operators are not restricted to methods returning IEnumerables, any method returning anything can be chosen.

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

In case you have instance methods named "Select" and "Where" that return a single object or extensions methods that are specific to your class and return a single object those will be used instead of the standard linq ones.

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

My guess is that either a "Select" or "Where" method defined in your class is making linq return a single value instead of a IEnumerable<T>.

我的猜测是,在您的类中定义的“选择”或“在哪里”方法使linq返回单个值而不是IEnumerable

#4


I didn't know different anonymous objects would be created depending on the query result. I guess they just wanted results to be of type IEnumerable

我不知道根据查询结果会创建不同的匿名对象。我猜他们只是希望结果是IEnumerable类型

How about using a foreach?

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

#5


This goes for all implicit types too. I must admit I keep forgetting this and that's how I came across this post.

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

if you have

如果你有

class ClassA {
               ...

               private string value;

               ...

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

              ...
}

you need to explictly cast the class to astring for comparison.

你需要明确地将类转换为astring进行比较。

so I usually do this

所以我通常这样做

    var myClassAStr = myClassA.ToString();

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

// do stuff with x
    ...

#6


try using

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

instead.

I think its the var that's causing your issue.

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

#7


Edit:

Read the error message. "Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."

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

One of these comparisions is with a type that is not int, string or guid. I'm guessing the Category.

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

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

Interestingly, LinqToSql will allow this construction. Don't know why LinqToEntities does not support this.

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

#8


I think you could also select the item you want another, simpler way by using lambda expressions.

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

and then proceeding as you would normally

然后像往常一样继续

相关文章