I'm trying to create a LINQ provider. I'm using the guide LINQ: Building an IQueryable provider series, and I have added the code up to LINQ: Building an IQueryable Provider - Part IV.
我正在尝试创建一个LINQ提供程序。我正在使用指南LINQ:构建一个IQueryable提供程序系列,我已经将代码添加到LINQ:构建一个IQueryable提供程序 - 第四部分。
I am getting a feel of how it is working and the idea behind it. Now I'm stuck on a problem, which isn't a code problem but more about the understanding.
我正在感受它是如何工作的以及它背后的想法。现在我遇到了一个问题,这不是代码问题,而是关于理解的问题。
I'm firing off this statement:
我发了这个声明:
QueryProvider provider = new DbQueryProvider();
Query<Customer> customers = new Query<Customer>(provider);
int i = 3;
var newLinqCustomer = customers.Select(c => new { c.Id, c.Name}).Where(p => p.Id == 2 | p.Id == i).ToList();
Somehow the code, or expression, knows that the Where
comes before the Select
. But how and where?
不知何故,代码或表达式知道在Select之前的Where。但是如何以及在哪里?
There is no way in the code that sorts the expression, in fact the ToString()
in debug mode, shows that the Select comes before the Where
.
在代码中没有办法对表达式进行排序,实际上调试模式下的ToString()表明Select位于Where之前。
I was trying to make the code fail. Normal I did the Where
first and then the Select
.
我试图让代码失败。正常我先做了Where,然后是Select。
So how does the expression sort this? I have not done any change to the code in the guide.
那么表达式如何排序呢?我没有对指南中的代码进行任何更改。
2 个解决方案
#1
10
The expressions are "interpreted", "translated" or "executed" in the order you write them - so the Where
does not come before the Select
表达式按照你编写的顺序“解释”,“翻译”或“执行” - 所以Where在选择之前不会出现
If you execute:
如果你执行:
var newLinqCustomer = customers.Select(c => new { c.Id, c.Name})
.Where(p => p.Id == 2 | p.Id == i).ToList();
Then the Where
is executed on the IEnumerable
or IQueryable
of the anonymous type.
然后在匿名类型的IEnumerable或IQueryable上执行Where。
If you execute:
如果你执行:
var newLinqCustomer = customers.Where(p => p.Id == 2 | p.Id == i)
.Select(c => new { c.Id, c.Name}).ToList();
Then the Where
is executed on the IEnumerable
or IQueryable
of the customer type.
然后在客户类型的IEnumerable或IQueryable上执行Where。
The only thing I can think of is that maybe you're seeing some generated SQL where the SELECT and WHERE have been reordered? In which case I'd guess that there's an optimisation step somewhere in the (e.g.) LINQ to SQL provider that takes SELECT Id, Name FROM (SELECT Id, Name FROM Customer WHERE Id=2 || Id=@i)
and converts it to SELECT Id, Name FROM Customer WHERE Id=2 || Id=@i
- but this must be a provider specific optimisation.
我唯一能想到的是,你可能会看到一些生成的SQL,其中SELECT和WHERE已被重新排序?在这种情况下,我猜想,有一个优化步骤某处(EG)的LINQ to SQL供应商,需要SELECT ID,姓名FROM(SELECT ID,名字从客户WHERE ID = 2 ||编号= @ I),并将其转换SELECT SELECT,Name FROM Customer WHERE Id = 2 || Id = @ i - 但这必须是提供者特定的优化。
#2
4
No, in the general case (such as LINQ to Objects) the select will be executed before the where statement. Think of it is a pipeline, your first step is a transformation, the second a filter. Not the other way round, as it would be the case if you wrote Where...Select.
不,在一般情况下(例如LINQ to Objects),select将在where语句之前执行。想想它是一个管道,你的第一步是转型,第二步是过滤。不是相反,如果你写了Where ... Select就是这种情况。
Now, a LINQ Provider has the freedom to walk the expression tree and optimize it as it sees fit. Be aware that you may not change the semantics of the expression though. This means that a smart LINQ to SQL provider would try to pull as many where
clauses it can into the SQL query to reduce the amount of data travelling over the network. However, keep the example from Stuart in mind: Not all query providers are clever, partly because ruling out side effects from query reordering is not as easy as it seems.
现在,LINQ提供程序可以*地遍历表达式树并在其认为合适时对其进行优化。请注意,您可能不会更改表达式的语义。这意味着智能LINQ to SQL提供程序会尝试将尽可能多的where子句引入SQL查询,以减少通过网络传输的数据量。但是,请记住Stuart的例子:并非所有查询提供者都很聪明,部分原因是排除查询重新排序的副作用并不像看起来那么容易。
#1
10
The expressions are "interpreted", "translated" or "executed" in the order you write them - so the Where
does not come before the Select
表达式按照你编写的顺序“解释”,“翻译”或“执行” - 所以Where在选择之前不会出现
If you execute:
如果你执行:
var newLinqCustomer = customers.Select(c => new { c.Id, c.Name})
.Where(p => p.Id == 2 | p.Id == i).ToList();
Then the Where
is executed on the IEnumerable
or IQueryable
of the anonymous type.
然后在匿名类型的IEnumerable或IQueryable上执行Where。
If you execute:
如果你执行:
var newLinqCustomer = customers.Where(p => p.Id == 2 | p.Id == i)
.Select(c => new { c.Id, c.Name}).ToList();
Then the Where
is executed on the IEnumerable
or IQueryable
of the customer type.
然后在客户类型的IEnumerable或IQueryable上执行Where。
The only thing I can think of is that maybe you're seeing some generated SQL where the SELECT and WHERE have been reordered? In which case I'd guess that there's an optimisation step somewhere in the (e.g.) LINQ to SQL provider that takes SELECT Id, Name FROM (SELECT Id, Name FROM Customer WHERE Id=2 || Id=@i)
and converts it to SELECT Id, Name FROM Customer WHERE Id=2 || Id=@i
- but this must be a provider specific optimisation.
我唯一能想到的是,你可能会看到一些生成的SQL,其中SELECT和WHERE已被重新排序?在这种情况下,我猜想,有一个优化步骤某处(EG)的LINQ to SQL供应商,需要SELECT ID,姓名FROM(SELECT ID,名字从客户WHERE ID = 2 ||编号= @ I),并将其转换SELECT SELECT,Name FROM Customer WHERE Id = 2 || Id = @ i - 但这必须是提供者特定的优化。
#2
4
No, in the general case (such as LINQ to Objects) the select will be executed before the where statement. Think of it is a pipeline, your first step is a transformation, the second a filter. Not the other way round, as it would be the case if you wrote Where...Select.
不,在一般情况下(例如LINQ to Objects),select将在where语句之前执行。想想它是一个管道,你的第一步是转型,第二步是过滤。不是相反,如果你写了Where ... Select就是这种情况。
Now, a LINQ Provider has the freedom to walk the expression tree and optimize it as it sees fit. Be aware that you may not change the semantics of the expression though. This means that a smart LINQ to SQL provider would try to pull as many where
clauses it can into the SQL query to reduce the amount of data travelling over the network. However, keep the example from Stuart in mind: Not all query providers are clever, partly because ruling out side effects from query reordering is not as easy as it seems.
现在,LINQ提供程序可以*地遍历表达式树并在其认为合适时对其进行优化。请注意,您可能不会更改表达式的语义。这意味着智能LINQ to SQL提供程序会尝试将尽可能多的where子句引入SQL查询,以减少通过网络传输的数据量。但是,请记住Stuart的例子:并非所有查询提供者都很聪明,部分原因是排除查询重新排序的副作用并不像看起来那么容易。