Linq IQueryable.Any () Usage

Below is my code. Please view it.

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

It works.

The following statements do not work.

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

The exception is

  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 

The exception is

  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. 

The Deploys class is a model built in the proxy class of the WCF data service client. I used "add service link" to create a WCF client proxy class.

But as for the general list, the code below is assumed. it will work fine.

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

My question

Why did the same method used in different classes get a different result (see method 2 and method 4).

Why 2 and 3 do not work.

Hope someone can help me. Thanks

+4
source share
1 answer

LINQ has the concept of "suppliers." When working with LINQ on different data sources, different things must be done for identical LINQ queries depending on the data source.

For example, if you want to use LINQ to query a database, you need to convert the LINQ query to an SQL query. When the data source is OData, the request needs to be converted to a URL. There are different providers for each of them, and each supplier supports a different subset of LINQ statements and other language constructs. LINQ-to-SQL, Entity Framework, and LINQ-to-NHibernate are three popular LINQ database access providers.

In your case, you are using WCF data services, which include the LINQ provider for OData. Since there is no way in OData to express the .Any() LINQ operator, an attempt to use it in a query with this provider throws an exception. Using .AsEnumerable() , you are essentially saying to stop using the OData LINQ provider at this point and start using the LINQ-to-Objects provider (which is not technically a provider, but conceptually you can consider it as one). This means that only what precedes .AsEnumerable() will be converted to an OData request, which will retrieve all Deploy objects that match .Where() , and after all of them are passed to the client, the client will execute the command .Any() by checking the number of Deploy entities received. This, of course, is bad, if there are a lot of such objects, this will lead to unwanted data transmission over the network, when all you need is a server (probably a database) to check if they exist. Unfortunately .Any() not supported by OData 1.0 (I don't know about OData 2.0).

Also, OData may not support .ToString() . You may need to directly compare Guid structures, i.e. Create a local variable containing the GUID value that you want to compare:

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

And then in the request, compare the GUID as follows:

 x.HostedEnvironment == g 
+5
source

All Articles