2015-01-16 6 views
0

Реализация поставщика для этого не так уж трудно:Как получить текст запроса экземпляра 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()); 
} 

он не работает.

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

+0

Независимо от того, используете ли вы синтаксис синтаксиса или синтаксис метода или выполняете ли операции в промежуточных переменных до того, как последующие операции будут вызваны, все буквально * zero * влияют на окончательный 'IQueryable'. – Servy

+0

Можете ли вы добавить, как создается 'somecontext'? –

+3

Как вы реализуете поставщик запросов, будет полностью зависеть от того, для чего вы создаете поставщика, как вы хотите его работать, какие операции вы хотите поддерживать, как вы хотите перевести различные операции LINQ на этот язык и т. Д. Как бы то ни было, вопрос нигде не подошел к ответственности. – Servy

ответ

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); 

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

Удачи.

+0

Спасибо, Крис. За последний год я прошел всю серию Мэтта и практиковал и даже написал собственный поставщик LINQ. Я не могу сформулировать свой вопрос, и он не делает себя очень ясным без информации, которую я не предоставил, возможно. Я на самом деле думаю, и я думаю, что мышление больше поможет мне достичь решения, которое мне нужно. Я думаю, что я почти там. Я должен опубликовать ответ на свой вопрос, как только у меня это получится. –

+0

Я действительно ценю вашу помощь. :-) –