跨关系查询 (LINQ to SQL)

更新:November 2007

您的类定义中对其他对象或其他对象的集合的直接引用相当于数据库中的外键关系。您可以通过使用点表示法在查询时利用这些关系来访问关系属性以及从一个对象定位到另一个对象。这些访问操作会转换成用等效的 SQL 表示的更为复杂的联接或关联子查询。

例如,下面的查询从订单定位到客户,以此方式将结果限制为只包括位于伦敦的客户的订单。

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim londonOrderQuery = _
From ord In db.Orders _
Where ord.Customer.City = "London" _
Select ord
        Northwnd db = new Northwnd(@"northwnd.mdf");

        IQueryable<Order> londonOrderQuery =
from ord in db.Orders
where ord.Customer.City == "London"
select ord;

如果关系属性不存在,您必须作为联接手动编写它们,就像您在 SQL 查询中进行编写时一样,如下面的代码所示:

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim londOrderQuery = _
From cust In db.Customers _
Join ord In db.Orders On cust.CustomerID Equals ord.CustomerID _
Select ord
        Northwnd db = new Northwnd(@"northwnd.mdf");
        IQueryable<Order> londonOrderQuery =
from cust in db.Customers
join ord in db.Orders on cust.CustomerID equals ord.CustomerID
where cust.City == "London"
select ord;

您可以使用关系属性来定义一次这种特殊关系。然后您就可以使用更为方便的点语法。但之所以存在关系属性,更重要的原因在于特定于域的对象模型通常定义为层次结构或关系图。您要进行编程的那些对象引用其他对象。如果对象与对象的关系相当于数据库中外键类型的关系,那么这只是一种令人庆幸的巧合而已。在这种情况下,可以很方便地通过访问属性来编写联接。

就这一点而言,关系属性在查询的结果方面要比作为查询本身的一部分重要。在查询检索到关于特定客户的数据后,类定义会指示客户下了订单。换言之,您希望特定客户的 Orders 属性是用该客户下的所有订单填充的集合。这实际上是您通过以此方式定义类声明的协定。即便查询并未请求订单,您也希望在那里看到这些订单。您希望自己的对象模型保持这样的错觉:它是数据库在内存中的扩展,并且相关对象立即可用。

既然您已经具备了关系,您就可以通过引用您的类中定义的关系属性来编写查询。这些关系引用相当于数据库中的外键关系。使用这些关系的操作会转换成用等效的 SQL 表示的更为复杂的联接。只要您已经定义关系(使用 AssociationAttribute 属性),您就无需在 LINQ to SQL 中编写显式联接的代码。

为帮助保持这种错觉,LINQ to SQL 实现了一种称作延迟加载的技术。有关更多信息,请参见 延迟加载与立即加载 (LINQ to SQL)

可以考虑用下面的 SQL 查询来投影 CustomerID-OrderID 对的列表:

SELECT t0.CustomerID, t1.OrderID
FROM   Customers AS t0 INNER JOIN
          Orders AS t1 ON t0.CustomerID = t1.CustomerID
WHERE  (t0.City = @p0)

下图以图形方式显示了表关系。

跨关系查询

若要通过使用 LINQ to SQL 获得相同的结果,您可以使用 Customer 类中已经存在的 Orders 属性引用。Orders 引用提供了执行查询和投影 CustomerID-OrderID 对所必需的信息,如下面的代码所示:

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim idQuery = _
From cust In db.Customers, ord In cust.Orders _
Where cust.City = "London" _
Select cust.CustomerID, ord.OrderID
        Northwnd db = new Northwnd(@"northwnd.mdf");
        var idQuery =
from cust in db.Customers
from ord in cust.Orders
where cust.City == "London"
select new { cust.CustomerID, ord.OrderID };

您也可以反向操作。也就是说,您可以查询 Orders,然后使用其 Customer 关系引用来访问关于关联的 Customer 对象的信息。下面的代码投影与前面相同的 CustomerID-OrderID 对,但这一次采用的方法是查询 Orders 而非 Customers。

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim idQuery = _
From ord In db.Orders _
Where ord.Customer.City = "London" _
Select ord.CustomerID, ord.OrderID
        Northwnd db = new Northwnd(@"northwnd.mdf");
        var idQuery =
from ord in db.Orders
where ord.Customer.City == "London"
select new { ord.Customer.CustomerID, ord.OrderID };

请参见

其他资源

LINQ to SQL 中的查询概念