查询表达式语法示例:导航关系

Entity Framework 中的导航属性是用于在关联末尾查找实体的快捷属性。 导航属性允许用户从一个实体导航到另一个实体,或通过关联集从一个实体导航到相关实体。 本主题提供查询表达式语法中的示例,说明如何在 LINQ to Entities 查询中通过导航属性导航访问关系。

这些示例中使用的 AdventureWorks 销售模型基于 AdventureWorks 示例数据库中的 Contact、Address、Product、SalesOrderHeader 和 SalesOrderDetail 表生成。

本主题中的示例使用以下 using/Imports 语句:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Globalization;
using System.Data.EntityClient;
using System.Data.SqlClient;
using System.Data.Common;

Option Explicit On
Option Strict On
Imports System.Data.Objects
Imports System.Globalization

示例 1

下面的示例使用Select方法获取所有联系人 ID,并计算每个联系人的欠款总额,其中这些联系人的姓氏为“周”。 Contact.SalesOrderHeader 导航属性用于获取每个联系人的 SalesOrderHeader 对象的集合。 Sum 方法使用 Contact.SalesOrderHeader 导航属性以汇总每个联系人的所有订单的应付款总计。

string lastName = "Zhou";
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    ObjectSet<Contact> contacts = context.Contacts;

    var ordersQuery = from contact in contacts
                      where contact.LastName == lastName
                      select new
                      {
                          ContactID = contact.ContactID,
                          Total = contact.SalesOrderHeaders.Sum(o => o.TotalDue)
                      };

    foreach (var contact in ordersQuery)
    {
        Console.WriteLine($"Contact ID: {contact.ContactID} Orders total: {contact.Total}");
    }
}
Dim lastName = "Zhou"
Using context As New AdventureWorksEntities
    Dim contacts As ObjectSet(Of Contact) = context.Contacts

    Dim ordersQuery = From contact In contacts _
                      Where contact.LastName = lastName _
                      Select New With _
                              {.ContactID = contact.ContactID, _
                              .Total = contact.SalesOrderHeaders.Sum(Function(o) o.TotalDue)}

    For Each order In ordersQuery
        Console.WriteLine("Contact ID: {0} Orders total: {1}", order.ContactID, order.Total)
    Next
End Using

示例 2

以下示例代码获取其姓氏为“周”的联系人的所有订单。 Contact.SalesOrderHeader 导航属性用于获取每个联系人的 SalesOrderHeader 对象的集合。 联系人的姓名和订单以匿名类型返回。

string lastName = "Zhou";
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    ObjectSet<Contact> contacts = context.Contacts;

    var ordersQuery = from contact in contacts
                      where contact.LastName == lastName
                      select new { LastName = contact.LastName, Orders = contact.SalesOrderHeaders };

    foreach (var order in ordersQuery)
    {
        Console.WriteLine($"Name: {order.LastName}");
        foreach (SalesOrderHeader orderInfo in order.Orders)
        {
            Console.WriteLine("Order ID: {0}, Order date: {1}, Total Due: {2}",
                orderInfo.SalesOrderID, orderInfo.OrderDate, orderInfo.TotalDue);
        }
        Console.WriteLine("");
    }
}
Dim lastName = "Zhou"
Using context As New AdventureWorksEntities
    Dim contacts As ObjectSet(Of Contact) = context.Contacts

    Dim ordersQuery = From contact In contacts _
                      Where contact.LastName = lastName _
                      Select New With _
                              {.LastName = contact.LastName, _
                               .Orders = contact.SalesOrderHeaders}

    For Each order In ordersQuery
        Console.WriteLine("Name: {0}", order.LastName)
        For Each orderInfo In order.Orders

            Console.WriteLine("Order ID: {0}, Order date: {1}, Total Due: {2}", _
                    orderInfo.SalesOrderID, orderInfo.OrderDate, orderInfo.TotalDue)
        Next

        Console.WriteLine("")
    Next
End Using

示例 3

以下示例使用 SalesOrderHeader.AddressSalesOrderHeader.Contact 导航属性来获取与每个订单关联的 AddressContact 对象集合。 联系人的姓氏、街道地址、销售订单号,以及每个运往西雅图订单的到期总额均以匿名类型返回。

string city = "Seattle";
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders;

    var ordersQuery = from order in orders
                      where order.Address.City == city
                      select new
                      {
                          ContactLastName = order.Contact.LastName,
                          ContactFirstName = order.Contact.FirstName,
                          StreetAddress = order.Address.AddressLine1,
                          OrderNumber = order.SalesOrderNumber,
                          TotalDue = order.TotalDue
                      };

    foreach (var orderInfo in ordersQuery)
    {
        Console.WriteLine("Name: {0}, {1}", orderInfo.ContactLastName, orderInfo.ContactFirstName);
        Console.WriteLine($"Street address: {orderInfo.StreetAddress}");
        Console.WriteLine($"Order number: {orderInfo.OrderNumber}");
        Console.WriteLine($"Total Due: {orderInfo.TotalDue}");
        Console.WriteLine("");
    }
}
Dim city = "Seattle"
Using context As New AdventureWorksEntities

    Dim orders As ObjectSet(Of SalesOrderHeader) = context.SalesOrderHeaders

    Dim ordersQuery = From order In orders _
                      Where order.Address.City = city _
                      Select New With { _
                                     .ContactLastName = order.Contact.LastName, _
                                     .ContactFirstName = order.Contact.FirstName, _
                                     .StreetAddress = order.Address.AddressLine1, _
                                     .OrderNumber = order.SalesOrderNumber, _
                                     .TotalDue = order.TotalDue}

    For Each orderInfo In ordersQuery
        Console.WriteLine("Name: {0}, {1}", orderInfo.ContactLastName, orderInfo.ContactFirstName)
        Console.WriteLine("Street address: {0}", orderInfo.StreetAddress)
        Console.WriteLine("Order number: {0}", orderInfo.OrderNumber)
        Console.WriteLine("Total Due: {0}", orderInfo.TotalDue)
        Console.WriteLine("")
    Next

End Using

示例 4

下面的示例使用该方法 Where 查找在 2003 年 12 月 1 日之后发出的订单,然后使用 order.SalesOrderDetail 导航属性获取每个订单的详细信息。

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    IQueryable<SalesOrderHeader> query =
        from order in context.SalesOrderHeaders
        where order.OrderDate >= new DateTime(2003, 12, 1)
        select order;

    Console.WriteLine("Orders that were made after December 1, 2003:");
    foreach (SalesOrderHeader order in query)
    {
        Console.WriteLine($"OrderID {order.SalesOrderID} Order date: {order.OrderDate:d} ");
        foreach (SalesOrderDetail orderDetail in order.SalesOrderDetails)
        {
            Console.WriteLine($"  Product ID: {orderDetail.ProductID} Unit Price {orderDetail.UnitPrice}");
        }
    }
}
Using context As New AdventureWorksEntities
    Dim orders As ObjectSet(Of SalesOrderHeader) = context.SalesOrderHeaders

    Dim query = _
        From order In orders _
        Where order.OrderDate >= New DateTime(2003, 12, 1) _
        Select order

    Console.WriteLine("Orders that were made after December 1, 2003:")
    For Each order In query
        Console.WriteLine("OrderID {0} Order date: {1:d} ", _
                order.SalesOrderID, order.OrderDate)
        For Each orderDetail In order.SalesOrderDetails
            Console.WriteLine("  Product ID: {0} Unit Price {1}", _
                orderDetail.ProductID, orderDetail.UnitPrice)
        Next
    Next
End Using

另请参阅