Future queries

Watch the Futures video on YouTube.

Build up a list of queries for the data you need, and the first time you access any of the results, PLINQO retrieves all the data in one round trip to the database server. Fewer round trips make applications faster.

To use future queries, import the CodeSmith.Data.Linq namespace and append .Future() to your queries:

// build up multiple queries
var q1 = db.User
    .ByEmailAddress("one@test.com")
    .Future();

var q2 = db.Task
    .Where(t => t.Summary == "Test")
    .Future();

// this triggers the loading of all the future queries
var users = q1.ToList();

No data is retrieved until q1.ToList() runs. Then PLINQO runs all the future queries automatically, as one batch.

You can also cache the results with FutureCache:

// cache these results for 120 seconds
var q1 = db.User
    .ByEmailAddress("one@test.com")
    .FutureCache(120);

var q2 = db.Task
    .Where(t => t.Summary == "Test")
    .FutureCache(120);

// this triggers the loading of all the future queries
var users = q1.ToList();

Creating future queries

You create future queries with the Future(), FutureFirstOrDefault() and FutureCount() extension methods.

var db = new TrackerDataContext();

// build up queries
var q1 = db.User
    .ByEmailAddress("one@test.com")
    .Future();

var q2 = db.Task
    .Where(t => t.Summary == "Test")
    .Future();

// this triggers the loading of all the future queries
var users = q1.ToList();

This example builds up two queries. As soon as one of them is enumerated, both are loaded in one batch.

A common scenario is paging a list of tasks. To set up the paging control, the UI also needs the total count. With future queries, you get both in one database call:

var db = new TrackerDataContext();

// base query
var q = db.Task.ByPriority(Priority.Normal);
// get total count
var q1 = q.FutureCount();
// get page
var q2 = q.Skip(pageIndex).Take(pageSize).Future();

// triggers sql execute as a batch
int total = q1.Value;
var tasks = q2.ToList();

Caching future queries

You can cache future queries with the same settings as the FromCache extension method. Each query is cached separately.

var db = new TrackerDataContext();

// cache for 120 seconds
CacheSettings cache = new CacheSettings(120);

// build up queries
var q1 = db.User
    .ByEmailAddress("one@test.com")
    .FutureCache(cache);

var q2 = db.Task
    .Where(t => t.Summary == "Test")
    .FutureCache(cache);

// this triggers the loading of all the future queries
var users = q1.ToList();

How future queries work

  1. Each future query creates an IFutureQuery object that keeps the IQueryable.
  2. The IFutureQuery object is stored in the IFutureContext.FutureQueries list of the DataContext that created the query. The DataContext must implement IFutureContext.
  3. When one of the IFutureQuery objects is enumerated, it calls back to IFutureContext.ExecuteFutureQueries() through the LoadAction delegate.
  4. ExecuteFutureQueries builds a batch query from all the stored IFutureQuery objects.
  5. All the IFutureQuery objects are updated with the results.

Note

Future queries don't support anonymous types.