Linq IQueryable.Any()用法

时间:2012-08-26 07:00:42

标签: linq linq-to-sql linq-to-entities

以下是我的代码。请查看它。

 1. bool isUnavailable = db.Deploys.Where(p => 
     p.HostEnvironmentId == Guid.Parse(host.ID) &&
     p.Status == (int)DeployStatus.Deploying).AsEnumerable().Any();

这个有效。

以下陈述不起作用。

2. bool isUnavailable = db.Deploys.Where(p => 
    p.HostEnvironmentId == Guid.Parse(host.ID) &&
    p.Status == (int)DeployStatus.Deploying).Any();//Error 

例外是

    An exception of type 'System.NotSupportedException' occurred in 
Microsoft.Data.Services.Client.DLL but was not handled in user code

    Additional information: The method 'Any' is not supported.


3. bool isUnavailable = db.Deploys.Where(p => 
        p.HostEnvironmentId.ToString() == host.ID &&
        p.Status == (int)DeployStatus.Deploying).AsEnumerable().Any();//Error

例外是

    An exception of type 'System.NotSupportedException' occurred in 
      Microsoft.Data.Services.Client.DLL but was not handled in user code
      Additional information: The expression (([10007].HostEnvironmentId.ToString() == 
"b7db845b-cec4-49af-8f4b-b419a4e44331") And ([10007].Status == 90)) is not supported.

Deploys类是在WCF数据服务的客户端代理类中构建的模型。我使用“添加服务引用”来创建WCF客户端代理类。

但是对于通用列表, 假设如下代码。它会工作正常。

4.bool b=servers.Where(d => 
   d.status == (int)Enums.ServerStatus.Deploying ||
   d.status == int)Enums.ServerStatus.Unavailable).Any();

我的问题是

  

为什么在不同的类中使用相同的方法会得到不同的结果。(参见方法2和方法4)。

     

为什么2和3不起作用。

希望有人可以帮助我。感谢

1 个答案:

答案 0 :(得分:5)

LINQ有'提供者'的概念。在不同数据源上使用LINQ时,根据数据源,相同的LINQ查询需要进行不同的操作。

例如,当您想使用LINQ查询数据库时,需要将LINQ查询转换为SQL查询。当数据源是OData时,需要将查询转换为URL。每个提供程序都有不同的提供程序,每个提供程序都支持LINQ运算符和其他语言结构的不同子集。 LINQ-to-SQL,实体框架和LINQ-to-NHibernate是三种流行的数据库访问LINQ提供程序。

在您的情况下,您正在使用WCF数据服务,其中包括OData的LINQ提供程序。由于在OData中无法表达.Any() LINQ运算符,因此尝试在具有该提供程序的查询中使用它会引发异常。通过使用.AsEnumerable(),你基本上就是说在那时停止使用OData LINQ提供程序并开始使用LINQ-to-Objects提供程序(从技术上讲它不是提供程序,但从概念上讲,你可以把它想象成一个)。这意味着只有.AsEnumerable()之前的内容才会被转换为OData查询,导致检索与Deploy匹配的所有.Where()实体,并且在它们全部转移到客户端之后,客户端将通过检查已收到的.Any()个实体的数量来执行Deploy。如果有很多这样的实体,这当然是不好的,当你想要的只是服务器端(可能是数据库)检查是否有任何这样的实体时,它将导致通过网络进行不必要的数据传输。不幸的是,OData 1.0不支持.Any()(我不知道OData 2.0)。

此外,OData也可能不支持.ToString()。您可能需要直接比较Guid结构,即创建一个包含您要比较的GUID值的局部变量:

var g = Guid.Parse("b7db845b-cec4-49af-8f4b-b419a4e44331")`

然后在查询中比较GUID,如:

x.HostedEnvironment == g