If your creating a custom query provider you may end up creating some custom query operators. I've found this to be a very powerful way to add additional functionality. If your doing this I would suggest also adding versions of your operators that work with IEnumerable<T>. The benefit of this is you can swap out your query provider for a List<T> (Or some other in memory collection that implements IEnumerable<T>) for unit testing.

Lets start with an sample query operator that represents a bubble sort:

public static class Queryable
{
    public static IQueryable<TSource> BubbleSort<TSource>(this IQueryable<TSource> source)
    {
        if (source == null) throw new ArgumentNullException("source");
        return source.Provider.CreateQuery<TSource>(
            Expression.Call(null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource) }), 
                            new[] { source.Expression }));
    }
}

Here we have some code that calls this custom query operator:

public static IQueryable<string> Sort(IQueryable<string> items)
{
    return items.BubbleSort();
}

This query operator likely maps to an out of process call somewhere (Like on a database server) but in our unit tests we want to keep it in memory. Instead of passing in our query provider we can pass in an in memory collection like List<T>:

[Test]
public void Test_Sort()
{
    var items = new List<string> { "Pauli", "Bohr", "Dirac", "Heisenberg" };
    var sorted = Sort(items.AsQueryable());
    // ... Asserts
}

Now if you were to do this it would fail because List<T> has no idea what BubbleSort() is. Although List<T> implements IQuerable<T> everything it does happens in memory as expected. When you treat an IEnumerable<T> as an IQueryable<T> it actually gets wrapped by a class called EnumerableQuery<T> which, when it executes, rewrites and compiles the expression tree. The interesting thing about this class (Technically delegated to the internal EnumerableRewriter class) is that it rewrites the expression tree so that arguments and return types of type IQueryable<T> get rewritten to be IEnumerable<T>. Same is true of Expression<Func<>> and Expression<Action<>>; they get rewritten to Func<> and Action<>. So if you want to be able to use an IQueryable<T> operator in memory, simply create a corresponding operator in the same type (This is required as far as I can tell) that operates on IEnumerable<T>:

public static class Queryable
{
    public static IQueryable<TSource> BubbleSort<TSource>(this IQueryable<TSource> source)
    {
        if (source == null) throw new ArgumentNullException("source");
        return source.Provider.CreateQuery<TSource>(
            Expression.Call(null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource) }), 
                            new[] { source.Expression }));
    }

    public static IEnumerable<TSource> BubbleSort<TSource>(this IEnumerable<TSource> source)
    {
        if (source == null) throw new ArgumentNullException("source");
        return SortLibrary.BubbleSort(source);
    }
}

Now your custom query operator will work against your custom query provider or an in memory collection. Obviously, the code that works against your in memory collection should behave the same as your out of process call or this is all for naught. There is one caveat however for query operators that execute the expression but still return an IQueryable<T>, for example:

public static IQueryable<TSource> Clone<TSource>(this IQueryable<TSource> source)
{
    if (source == null) throw new ArgumentNullException("source");
    return source.Provider.Execute<IQueryable<TSource>>(
        Expression.Call(null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new[] { typeof(TSource) }),
                        new[] { source.Expression }));
}

In this case you will need to have the corresponding IEnumerable<T> operator convert to and return an IQueryable<T>:

public static IQueryable<TSource> Clone<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) throw new ArgumentNullException("source");
    return Enumerable.Clone(source).AsQueryable();
}

If you don't do this the query provider will throw a type mismatch exception on the IEnumerable<T> your returning.