Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ passthrough provider?

I've implemented simple IQueryable and IQueryProvider classes that collect statistical data on LINQ expression trees. This part works fine. Next, I would like to pass the expression tree off to the default LINQ-to-Objects provider for evaluation, since I don't need to execute it any differently. In order words, I'd like my provider to collect stats as a side-effect, passing the query on to the default LINQ implementation.

However, I am having difficulty getting a handle to the default provider. I thought that I could simply save a reference to the original IEnumerable collection and then return the default provider (from my custom IQueryable) like:

IQueryProvider IQueryable.Provider
{
    get { return _my_provider.OriginalIEnum().AsQueryable().Provider; }
}

but this does not work correctly. The code eventually throws a StackOverflowException. What I think is happening (gleaned from single-stepping in debug mode) is that the LINQ runtime fetches the provider from the above method, then it fetches the expression tree from my custom IQueryable, and then it notices that the top-level expression is my custom IQueryable. So it starts the process over again, trying to find the appropriate provider. It does this endlessly until a stack overflow occurs.

Right now, the only thing I can think of is to come up with another visitor which produces another expression tree with the custom IQueryable nodes removed so that the LINQ runtime will call the default provider. That's a fair amount of work, since I need to visit every leaf to ensure that there are no nested Call expressions which call my custom IQueryable again. Is there a simpler approach?

Thanks for the help.

like image 900
Dan Barowy Avatar asked Jun 07 '13 01:06

Dan Barowy


1 Answers

It turns out that the real issue here is exactly the one described in Pass LINQ expression to another QueryProvider.

like image 58
Dan Barowy Avatar answered Nov 12 '22 09:11

Dan Barowy