So I did a bit of digging, and the issue is to do with the way the TestDbAsyncEnumerable<T>
exposes the IQueryProvider
. My best guess as to the reasoning is below, and the solution below that.
TestDbAsyncEnumerable<T>
inherits from EnumerableQuery<T>
, which in turn inherits from IQueryable<T>
, and explicitly implements the Provider
property of this interface:
IQueryProvider IQueryable.Provider { get ... }
Given that it's implemented explicitly, I am assuming that the LINQ internals explicitly cast a type before trying to get the Provider
:
((IQueryable<T>)source).Provider.CreateQuery(...);
I don't have a source on hand (and can't be bothered looking for one), but I believe the type binding rules are different for explicit implementations; essentially, the Provider
property on your TestDbAsyncEnumerable<T>
is not considered to be an implementation of IQueryable<T>.Provider
as an explicit one exists further up the chain, so your TestDbAsyncQueryProvider<T>
is never returned.
The fix for this is to make TestDbAsyncEnumerable<T>
also inherit IQueryable<T>
and explicitly implement the Provider
property, as below (adjusted from the MSDN article you linked):
public class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T>
{
public TestDbAsyncEnumerable(IEnumerable<T> enumerable) : base(enumerable)
{ }
public TestDbAsyncEnumerable(Expression expression) : base(expression)
{ }
public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
IQueryProvider IQueryable.Provider
{
get { return new TestDbAsyncQueryProvider<T>(this); }
}
}