Up Query using LINQ
DevForce 2010 Resource Center » DevForce development » Query » Query using LINQ » Execute scalar query asynchronously

Execute scalar query asynchronously

Last modified on August 15, 2012 17:22

A scalar immediate execution query is a LINQ query which performs an aggregation (such as Count or Group) or returns only one element (such as First or Single).  Because these methods force immediate execution of the query they can't be directly used with asynchronous queries, but using the AsScalarAsync method you can execute scalar immediate execution queries asynchronously.


The problem

You've probably noticed something about a query like the following:

C#
int ct = manager.Customers.Count();

It doesn't return a query object (an EntityQuery<T>) as other queries do.  Instead, it returns the count of the items in the entity set.

Or consider another example:

C#
Customer cust = manager.Customers.First();

It too doesn't return a query, but instead the first customer.

Both these queries are immediate execution queries in LINQ.  They differ from the usual deferred execution queries which allow you to build a query in one step and execute the query at a later time.  Immediate execution queries execute, well, immediately, and synchronously; you can't separate the creation of the query from the execution.  

In an asynchronous environment such as Silverlight, where all queries sent to the EntityServer must be executed asynchronously, immediate execution queries pose a problem.  For example, you can't do the following:

C#
// Will not work!
var query = manager.Customers.First();
query.ExecuteAsync();

AsScalarAsync

Enter the DevForce AsScalarAsync operator and the EntityScalarAsyncExtensions .  It's easiest to understand this with an example.

C#
var op = manager.Customers.AsScalarAsync().Count();
op.Completed += (o, e) => {
 int ct = e.Result;
};

This looks much the same as our earlier synchronous example, with two important differences.  One, AsScalarAsync is called to convert the query to an IEntityScalarQuery<T> before the Count method is called.  Second, an EntityScalarQueryOperation<T> operation object is returned.  The query has been executed immediately, but asynchronously.  As with any asynchronous query you can provide a callback or listen on its Completed event.

Like their synchronous counterparts, these methods can also accept a predicate.  For example,

C#
var op = manager.Employees.AsScalarAsync().First(e => e.LastName.StartsWith("D"));
op.Completed += (o, e) => {
  Employee emp = e.Result;
};

You can also write more complex queries, such as the one below using an Include:

C#
var op = manager.Employees.Include("Orders").AsScalarAsync().FirstOrNullEntity(e => e.Id == 1);
op.Completed += (o, e) => {
  Employee emp = e.Result;
  var orders = emp.Orders;  // Will not be pending.
};

Here's a query built dynamically:

C#
var query = EntityQuery.Create(typeof(Customer));
var pd = PredicateBuilder.Make("CompanyName", FilterOperator.StartsWith, "D");
var op = query.Where(pd).AsScalarAsync().First();
op.Completed += (o, e) => {
  var cust = e.Result;
};

The supported immediate execution methods are: All, Any, Average, Contains, Count, First, FirstOrDefault, FirstOrNullEntity, LongCount, Max, Min, Single, SingleOrDefault, SingleOrNullEntity, and Sum.  Examples of each are provided in the API documentation .

Created by DevForce on April 24, 2011 14:55

This wiki is licensed under a Creative Commons 2.0 license. XWiki Enterprise 3.2 - Documentation. Copyright © 2015 IdeaBlade