第三個例子是M : M的關系
var q =
from e in db.Employees
from et in e.EmployeeTerritorIEs
where e.City == "Seattle"
select new {e.FirstName, e.LastName, et.Territory.TerritoryDescription};
M:M的關系,一般會涉及三個表。(如果,有一個表是自關聯的,那有可能只有2個表。)在這裡,涉及Employees, EmployeeTerritories, Territories共三個表。它們的關系是1 : M : 1. Employees和Territories沒有很明確的關系。這個例子和上一個不同的是,它是在Select字句中,牽扯到TerritorIEs表。其生成的T-sql為
SELECT [t0].[FirstName], [t0].[LastName], [t2].[TerritoryDescription]
FROM [dbo].[Employees] AS [t0]
CROSS JOIN [dbo].[EmployeeTerritorIEs] AS [t1]
INNER JOIN [dbo].[TerritorIEs] AS [t2] ON [t2].[TerritoryID] = [t1].[TerritoryID]
WHERE ([t0].[City] = @p0) AND ([t1].[EmployeeID] = [t0].[EmployeeID])
-- @p0: Input String (Size = 7; Prec = 0; Scale = 0) [Seattle]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 2.0.20612.0
最後一個例子是自關聯的,並且夾帶了條件
var q =
from e1 in db.Employees
from e2 in e1.Employees
where e1.City == e2.City
select new {
FirstName1 = e1.FirstName, LastName1 = e1.LastName,
FirstName2 = e2.FirstName, LastName2 = e2.LastName,
e1.City
};
其T-sql為
SELECT [t0].[FirstName], [t0].[LastName], [t1].[FirstName] AS [FirstName2], [t1].[LastName] AS [LastName2], [t0].[City]
FROM [dbo].[Employees] AS [t0], [dbo].[Employees] AS [t1]
WHERE ([t0].[City] = [t1].[City]) AND ([t1].[ReportsTo] = [t0].[EmployeeID])
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 2.0.20612.0
從上面的例子我們可以看出,Dlinq以非常靈活的方式,處理其內部各表的關系。它不須顯式的聲明需要關聯到那個表,也可以放在Where和Select等子句中,隱式關聯。
GroupJoin
當dlinq語句中,有join而且還有into時,它會被翻譯為GroupJoin.我們先來看第一個例子。
var q =
from c in db.Customers
join o in db.Orders on c.CustomerID equals o.CustomerID into orders
select new {c.ContactName, OrderCount = orders.Count()};
本系列曾在C#3.0入門系列(八)-之GroupBy操作 一文中,第一次談到到into。into的概念是對其結果進行重新命名。為什麼需要重新命名呢?我們以本例為例。One To Many的關系中,左邊是one,它每條記錄叫做c(from c in db.Customers),右邊是many,其每條記錄叫做o ( join o in db.Orders ),每對應左邊的一個c,都會有一組o,那這一組o,就叫做orders,也就是說,我們把一組o命名為orders,這就是into用途。(和groupby中類似)。這也就是為什麼在select語句中,orders可以調用聚合函數Count。
在這個例子中,翻譯的t-sql為
SELECT [t0].[ContactName], (
SELECT COUNT(*)
FROM [dbo].[Orders] AS [t1]
WHERE [t0].[CustomerID] = [t1].[CustomerID]
) AS [value]
FROM [dbo].[Customers] AS [t0]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 2.0.20612.0
dlinq很聰明,直接用其內欠的t-sql返回值作為字段值。