Как получить текст запроса экземпляра IQueryable<T>, для которого вызывается этот оператор?

Реализация провайдера для этого не так сложна:

var query = from foo in someContext.Foos
                   where foo.Bar == "bar" && foo.Gaz > 4
                   select foo;

Но если я соединю вместе два оператора, вот так:

var chained1 = (from foo in someContext.Foos
                         where foo.Bar == "bar"
                         select foo)
                         .Where(f => f.Gaz > 4);

или если бы я сделал это:

var chained2 = chained1.Take(10);

Как бы я это реализовал?

При оценке текущего вызова метода или оператора в VisitMethodCall, Я посещаю экземпляр / объект / выражение, на котором сделан вызов метода. Это должно позвонить VisitConstant для оценки / перевода / переписывания этого выражения экземпляра.

Затем в VisitConstant если я сделаю это:

if (typeof(IQueryable).IsAssignableFrom(node.Type))
{
    _builder.Append((node.Value as IQueryable).ToString());
}

это не работает

Как получить текст запроса для ранее созданного запроса?

1 ответ

Это хорошая серия, которая может помочь вам в этом: http://blogs.msdn.com/b/mattwar/archive/2007/07/31/linq-building-an-iqueryable-provider-part-ii.aspx

В вашем примере это псевдокод, который нужно сделать (для вашего Take пример):

VisitMethodCallExpression получает вызов выражения с методом Takeвам нужно будет сделать:

_sb.Append("SELECT * FROM (");
Visit(..chained1..); // generate query for chained1 to _sb (recursively)
_sb.Append(") LIMIT "); 
VisitConstant(TakeMethodInfo.LambdaExpression);

Как видите, это будет работать, но это приводит к избыточным подзапросам. Вы можете прочитать больше об этом здесь: http://blogs.msdn.com/b/mattwar/archive/2008/01/16/linq-building-an-iqueryable-provider-part-ix.aspx

Удачи.

Другие вопросы по тегам