0

为此实现提供程序并不难:

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

它不起作用。

如何获取先前构建的查询的查询文本?

4

1 回答 1

1

这是一个很好的系列,可以让你继续前进:http: //blogs.msdn.com/b/mattwar/archive/2007/07/31/linq-building-an-iqueryable-provider-part-ii.aspx

在您的示例中,这是一个伪代码应该做什么(对于您的Take示例):

VisitMethodCallExpression使用 method 调用表达式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

祝你好运。

于 2015-01-16T17:37:12.693 回答