在LINQ中,我可以执行如下联接:
from c in dc.Customers
join o in dc.Orders on c.custid equals o.custid ...
但是,左连接要复杂得多:
from c in dc.Customers
join o in dc.Orders on c.custid equals o.custid
into temp from x in temp.DefaultIfEmpty() ...
为什么LINQ的设计者不能用这样的东西使事情变得简单(更像SQL)呢?
from c in dc.Customers
left join o in dc.Orders on c.custid equals o.custid ...
2条答案
按热度按时间0lvr5msh1#
why couldn't the designers of Linq make things simple (more sql like)
They could have. But your definition of simple (as a sql programmer) is not the same as the OO programmer's definition of simple. Linq (in C#) is a query technology for OO programmers, first. An example of this is why select comes last. That's to fulfill scope rules in C# and intellisense support in the editor.
These programmers maybe don't get
LEFT JOIN
(and get really confused if you sayLEFT OUTER JOIN
- thinking there's some difference, like one inherits from the other).What they do understand is
GROUP JOIN
, which behaves in a similar manner.All that
DefaultIfEmpty
stuff does is unpack the group - flattening the results into row/column form - away from the OO programmer's natural heirarchical form.DefaultIfEmpty
is not semantically necessary to get to the results.Here's the same query in method form - which the compiler generates from the above and which I prefer:
Could you state that in terms of his example?
This query gives you customers, with their orders as an attached collection. The orders collection might be empty. If you have 50 customers and 1000 orders, you will have 50 customers in the result.
This query gives you a CustomerOrder row. If a customer has 5 orders, the customer will appear 5 times, each time matched to a different order. If the customer has 0 orders, the customer will appear once matched to a null order. If you have 50 customers and 1000 orders, you will have 50-1049 rows after the join and the meaning of an element in the result is hard to define.
If they implemented
left join
, it would require the result shape of the second example. Once I used thegroup join
, which is better, I wouldn't implement theleft join
in one step either. Hierarchical shaping of query results is great.5cg8jx4n2#
可能是因为Linq表达式在编译器中只是syntactic sugar,编译器将它们转换为方法调用,所以查询语法是面向对象系统的一个有漏洞的抽象。
因为你实际上并不是在写SQL,所以一定会有底层技术表现不同的情况。添加一个类似SQL的“左连接”可能比你想象的要难得多。
有些人显然不知道Linq表达式是如何工作的,所以这里有一个进一步的解释。
如果我参加这个测试课程:
list.Where(l => l == "test2")
会编译成与from l in list where l == "test2" select l
相同的程式码。在这两种情况下,编译器都会产生匿名方法委派:这就是我所说的语法糖的意思。查询表达式并没有给语言添加任何新的东西,它们只是提供了一种使用现有语言特性的更简单的方法。