Как получить текст запроса экземпляра 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
Удачи.