除了查询单个表,还可以在 LINQ to DataSet 中执行跨表查询。 这可以通过使用“联接”来完成。 联接是一个数据源中的对象与共享另一数据源中的通用属性的对象(例如产品或联系人 ID)的关联。 在面向对象的编程中,对象之间的关系相对容易导航,因为每个对象都有引用另一个对象的成员。 但是,在外部数据库表中,导航关系并不简单。 数据库表不包含内置关系。 在这些情况下,联接操作可用于匹配每个来源中的元素。 例如,给定两个包含产品信息和销售信息的表,可以使用联接作来匹配同一销售订单的销售信息和产品。
Language-Integrated 查询(LINQ)框架提供两个联接运算符, Join 以及 GroupJoin。 这些运算符执行 等值联接:即,当两个数据源的键相等时,才进行联接。 (相比之下,Transact-SQL 支持除 equals
之外的联接运算符,如 less than
运算符。)
在关系数据库术语中, Join 实现内部联接。 内部联接是一种联接类型,其中仅返回那些在相反数据集中具有匹配项的对象。
操作符 GroupJoin 在关系数据库术语中没有直接对应的等效项;它们实现了内部联接和左外部联接的超集。 左外部联接是指返回第一个(左侧)集合的每个元素的联接,尽管第二个集合中没有关联元素。
有关联接的详细信息,请参阅联接操作。
示例:
以下示例执行 AdventureWorks 示例数据库中的 SalesOrderHeader
和 SalesOrderDetail
表的传统联接,以获取 8 月份的在线订单。
// 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($"{order.SalesOrderID}\t{order.SalesOrderDetailID}\t{order.OrderDate:d}\t{order.ProductID}");
}
' 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