跨表查询 (LINQ to DataSet)
除了查询单个表外,也可以在 LINQ to DataSet 中执行交叉表查询。 这可以通过使用“联接”来完成。 联接就是将一个数据源中的对象与另一个数据源中具有相同公共属性的对象(例如产品或联系人 ID)相关联。 在面向对象的编程中,由于每个对象都有引用另一个对象的成员,所以对象间的关系相对较容易导航。 但在外部数据库表中,导航关系不像这样简单。 数据库表不包含内置关系。 在这些情况下,可以通过联接操作来匹配每个源中的元素。 例如,假设有两个分别包含产品信息和销售信息的表,您可以使用联接操作来匹配同一销售订单的销售信息和产品。
语言集成查询 (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("{0}\t{1}\t{2:d}\t{3}",
order.SalesOrderID,
order.SalesOrderDetailID,
order.OrderDate,
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