跨資料表查詢 (LINQ to DataSet)
除了查詢單一資料表以外,您也可以在 LINQ to DataSet 中執行跨資料表查詢。您可以使用「聯結」(Join) 完成這項目的。 聯結是指某個資料來源中的物件與另一個資料來源中共用相同屬性之物件的關聯,例如產品或連絡人識別碼。 在物件導向的程式設計中,物件之間的關聯性相當容易瀏覽,因為每個物件都具有參考另一個物件的成員。不過,在外部資料庫資料表中,瀏覽關聯性就沒有這麼直接。 資料庫資料表不包含內建關聯性。在這些情況中,聯結作業可用來比對每個來源的項目。 例如,假設有兩個包含產品資訊和銷售資訊的資料表。此時,您可能會使用聯結作業,針對相同銷售訂單比對銷售資訊和產品。
Language-Integrated Query (LINQ) 架構提供兩個聯結運算子:Join 和 GroupJoin。這些運算子會執行「等聯結」(Equi-Join):亦即,只有在索引鍵相等時才比對兩個資料來源的聯結。 (相較之下,Transact-SQL 支援 equals 以外的聯結運算子,例如 less than 運算子)。
在關聯式資料庫詞彙中,Join 會實作內部聯結 (Inner Join)。 內部聯結是一種聯結類型,而這種聯結只會傳回在相對資料集內部具有相符項目的物件。
GroupJoin 運算子在關聯式資料庫詞彙中沒有直接的對等項目,而且它們會實作內部聯結和左外部聯結 (Left Outer Join) 的超集。左外部聯結是指傳回第一個 (左) 集合之每個項目的聯結,即使它在第二個集合中沒有相互關聯的項目也一樣。
如需聯結的詳細資訊,請參閱聯結作業。
範例
下列範例會針對 AdventureWorks 範例資料庫的 SalesOrderHeader 和 SalesOrderDetail 資料表執行傳統聯結,以便取得八月份的線上訂單。
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim orders As DataTable = ds.Tables("SalesOrderHeader")
Dim details As DataTable = ds.Tables("SalesOrderDetail")
Dim query = _
From order In orders.AsEnumerable() _
Join detail In details.AsEnumerable() _
On order.Field(Of Integer)("SalesOrderID") Equals _
detail.Field(Of Integer)("SalesOrderID") _
Where order.Field(Of Boolean)("OnlineOrderFlag") = True And _
order.Field(Of DateTime)("OrderDate").Month = 8 _
Select New With _
{ _
.SalesOrderID = order.Field(Of Integer)("SalesOrderID"), _
.SalesOrderDetailID = detail.Field(Of Integer)("SalesOrderDetailID"), _
.OrderDate = order.Field(Of DateTime)("OrderDate"), _
.ProductID = detail.Field(Of Integer)("ProductID") _
}
For Each order In query
Console.WriteLine(order.SalesOrderID & vbTab & _
order.SalesOrderDetailID & vbTab & _
order.OrderDate & vbTab & _
order.ProductID)
Next
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable orders = ds.Tables["SalesOrderHeader"];
DataTable details = ds.Tables["SalesOrderDetail"];
var query =
from order in orders.AsEnumerable()
join detail in details.AsEnumerable()
on order.Field<int>("SalesOrderID") equals
detail.Field<int>("SalesOrderID")
where order.Field<bool>("OnlineOrderFlag") == true
&& order.Field<DateTime>("OrderDate").Month == 8
select new
{
SalesOrderID =
order.Field<int>("SalesOrderID"),
SalesOrderDetailID =
detail.Field<int>("SalesOrderDetailID"),
OrderDate =
order.Field<DateTime>("OrderDate"),
ProductID =
detail.Field<int>("ProductID")
};
foreach (var order in query)
{
Console.WriteLine("{0}\t{1}\t{2:d}\t{3}",
order.SalesOrderID,
order.SalesOrderDetailID,
order.OrderDate,
order.ProductID);
}