Using LinqToAnything to create an IQueryable for a Stored Proc or Web Service

If you ever have a need for an IQueryable, but your data source doesn't come with a LINQ Provider, you can use a library I created called LinqToAnything. I've used it to connect my DataTables library to a stored procedure, and to Azure Table Storage.

Take one paged data access method:

    public void IEnumerable<Product> GetProducts(int skip, int take, string category) 
    { 
    ... call Stored Proc or webservice here ... 
    };

    class Product
    {
         ...
         public string Category {get;set;}
    }

We need to create a lambda with the signature Func<LinqToAnything.QueryInfo, IEnumerable<T>> (or a similar method) - this will map from a QueryInfo instance to the data access method. The QueryInfo object contains a flattened, simplified view of the Linq Expression tree.

    IQuerable<Product> queryable = new DelegateQueryable<Product>(WrapperMethod)

    ....

    IEnumerable<Product>> WrapperMethod(QueryInfo queryInfo) {

        //extract the category value from the query info object
        var category = queryInfo.Clauses
            .OfType<Where>()
            .Where(c => c.PropertyName == "Category" && c.Operator == "Equals")
            .Select(c => c.Value);

        return GetProducts(queryInfo.Take, queryInfo.Skip, category);
    };

A QueryInfo object contains:

  • a Take, a Skip and an OrderBy property
  • an enumerable of Clause objects (Wheres, or Ors). The Clause objects contain the original Expression object they were built from, so you can re-apply or examine the original Expression.

Please see QueryInfo.cs for info on what queries are supported, and what operators you can use.

It makes it easy to disassemble and reconstruct Linq queries, so you can do custom stuff to them.

To get hold of it:

Install-Package LinqToAnything

Coming soon: how to use LinqToAnything to prevent over-querying of an OData (or other IQueryable based) API.