2. Querying with LINQ
Because
the Table service is implemented using ADO.NET Data Services, you can
use the WCF Data Services client library to perform server-side queries
using LINQ rather than querying the REST API directly.
The following code shows how the Products table was exposed in the ProductContext class :
public DataServiceQuery<Product> Products
{
get{return CreateQuery<Product>("Products");}
}
Rather than executing and returning a list of products from the Products table stored in the Table service, the Products
property will generate and return a new query that won’t be executed
until the collection is enumerated. Because the execution of the DataServiceQuery is deferred, you can modify the returned query to include any filters that you may require prior to executing the query.
Because DataServiceQuery implements the IQueryable
interface, you can define the query that should be executed by the
Table service in your application by using LINQ. The following code is a
LINQ query that will return all the products in the Shirts partition of the Products table:
var shirts = from shirt in shirtContext.Products
where shirt.PartitionKey == "Shirts"
select shirt;
foreach (var shirt in shirts)
{
}
In the preceding query, the Products property of shirtContext is IQueryable,
so you can make this the data source of a LINQ query. Because the query
won’t be passed to the Table service for execution until the for
loop is executed, you can add additional filter criteria to the query
(such as restricting the returned data to only those shirts that reside
in the Shirts partition).
Note
If you don’t include the
where criteria in the preceding LINQ statement, the underlying REST API
that’s executed would be the same as the call made in listing 1.
3. Filtering data with the REST API
In the previous section, we looked at a LINQ query that included a WHERE clause, restricting the data returned from the Table service to include only those shirts in the Shirts partition. We’ll now look at how you can modify your use of the REST API to perform server-side filtering.
Returning a Single Entity
As stated previously, the combination of the PartitionKey and RowKey
uniquely identifies an entity in a table. If you wish to return a
single entity from a table, and you know these two values, you can
efficiently return the entity. The following URI would return the RedShirt entity from the Shirts partition:
http://127.0.0.1:10002/devstoreaccount1/Products(PartitionKey='Shirts',RowKey='RedShirt')
To execute this query, you could modify the console application in listing 12.4, replacing the URI with one here. The Atom XML returned from the query would be similar to the data returned in listing 2, but it would only contain the RedShirt entity.
Querying Entities
If you need to return
zero or more entities based upon some filter criteria (such as all
shirts that cost $10), you could use the following URI to define the
REST query:
http://127.0.0.1:10002/devstoreaccount1/Products$filter=<query>
Just replace the <query> in the URI with the filter that you want to run server-side. Again, you can modify the console application in listing 1 to use this URI. When the query is executed, all entities that match the query will be returned in Atom XML format, as in listing 2.
Query Expressions
Let’s take a quick look at the
syntax of the query expression applied in the REST API. (We’ll look at
using these queries in the more familiar LINQ syntax in the next
section.)
As of the PDC 2009 release, the Table service only supports the query expressions listed in table 2.
Table 12.2. Query expressions supported by the Table service
Supported query expression | Description (C# equivalent operator) |
---|
eq | Equals (==) |
gt | Greater than (>) |
ge | Greater than or equal to (>=) |
lt | Less than (<) |
le | Less than or equal to (<=) |
ne | Not equal to (!=) |
and | And (&&)—Boolean properties only |
not | Not (!)—Boolean properties only |
or | Or (||)—Boolean properties only |
You
could apply these queries to a REST API query to return all shirts with
the description “A Red Shirt”. The URI would look like this:
http://127.0.0.1:10002/devstoreaccount1/Products?$filter=Description%20eq%20'A%20Red%20Shirt'
To return all shirts in the Shirts partition that have the description “A Red Shirt”, you’d use the following URI:
http://127.0.0.1:10002/devstoreaccount1/Products?$filter=PartitionKey%20eq%20'Shirts'%20and%20Description%20eq%20'A%20Red%20Shirt'%