Chaining IQueryables together
- by Matt Greer
I have a RIA Services based app that is using Entity Framework on the server side (possibly not relevant). In my real app, I can do something like this.
EntityQuery<Status> query = statusContext.GetStatusesQuery().Where(s => s.Description.Contains("Foo"));
Where statusContext is the client side subclass of DomainContext that RIA Services was kind enough to generate for me. The end result is an EntityQuery<Status> object who's Query property is an object that implements IQueryable and represents my where clause. The WebDomainClient is able to take this EntityQuery and not just give me back all of my Statuses but also filtered with my where clause.
I am trying to implement this in a mock DomainClient. This MockDomainClient accepts an IQueryably<Entity> which it returns when asked for.
But what if the user makes the query and includes the ad hoc additional query? How can I merge the two together?
My MockDomainClient is (this is modeled after this blog post) ...
public class MockDomainClient : LocalDomainClient
{
private IQueryable<Entity> _entities;
public MockDomainClient(IQueryable<Entity> entities)
{
_entities = entities;
}
public override IQueryable<Entity> DoQuery(EntityQuery query)
{
if (query.Query == null)
{
return _entities;
}
// otherwise want the union of _entities and query.Query, query.Query is IQueryable
// the below does not work and was a total shot in the dark:
//return _entities.Union(query.Query.Cast<Entity>());
}
}
public abstract class LocalDomainClient : System.ServiceModel.DomainServices.Client.DomainClient
{
private SynchronizationContext _syncContext;
protected LocalDomainClient()
{
_syncContext = SynchronizationContext.Current;
}
...
public abstract IQueryable<Entity> DoQuery(EntityQuery query);
protected override IAsyncResult BeginQueryCore(EntityQuery query, AsyncCallback callback, object userState)
{
IQueryable<Entity> localQuery = DoQuery(query);
LocalAsyncResult asyncResult = new LocalAsyncResult(callback, userState, localQuery);
_syncContext.Post(o => (o as LocalAsyncResult).Complete(), asyncResult);
return asyncResult;
}
...
}