演练:跨关系查询 (C#)

本演练演示如何使用 LINQ to SQL 关联来表示数据库中的外键关系。

注释

计算机可能会在以下说明中显示某些 Visual Studio 用户界面元素的不同名称或位置。 你拥有的 Visual Studio 版本以及所使用的设置决定了这些元素。 有关更多信息,请参阅 自定义 IDE

本演练是使用 Visual C# 开发设置编写的。

先决条件

你必须已完成演练:简单对象模型和查询(C#)。 本演练建立在该演练基础之上,包括在 c:\linqtest5 中须存在 northwnd.mdf 文件。

概述

本演练由三个主要任务组成:

  • 添加实体类以表示示例 Northwind 数据库中的 Orders 表。

  • 将批注补充到Customer类,以增强Customer类和Order类之间的关系。

  • 创建并运行查询以测试使用Order类获取Customer信息。

跨表映射关系

Customer 定义后,创建 Order 包含以下代码的实体类定义,该定义指示 Order.Customer 与外键 Customer.CustomerID相关。

添加 Order 实体类

  • 在类后面 Customer 键入或粘贴以下代码:

    [Table(Name = "Orders")]
    public class Order
    {
        private int _OrderID = 0;
        private string _CustomerID;
        private EntityRef<Customer> _Customer;
        public Order() { this._Customer = new EntityRef<Customer>(); }
    
        [Column(Storage = "_OrderID", DbType = "Int NOT NULL IDENTITY",
        IsPrimaryKey = true, IsDbGenerated = true)]
        public int OrderID
        {
            get { return this._OrderID; }
            // No need to specify a setter because IsDBGenerated is
            // true.
        }
    
        [Column(Storage = "_CustomerID", DbType = "NChar(5)")]
        public string CustomerID
        {
            get { return this._CustomerID; }
            set { this._CustomerID = value; }
        }
    
        [Association(Storage = "_Customer", ThisKey = "CustomerID")]
        public Customer Customer
        {
            get { return this._Customer.Entity; }
            set { this._Customer.Entity = value; }
        }
    }
    

对 Customer 类进行批注

在此步骤中,为类添加 Customer 批注以指示其与 Order 类的关系。 (这一添加并非严格必要,因为定义任一方向的关系足以创建链接。但添加此批注确实使你能够轻松地在任一方向导航对象。

对 Customer 类进行批注

  • 将以下代码键入或粘贴到 Customer 类中:

    private EntitySet<Order> _Orders;
    public Customer()
    {
        this._Orders = new EntitySet<Order>();
    }
    
    [Association(Storage = "_Orders", OtherKey = "CustomerID")]
    public EntitySet<Order> Orders
    {
        get { return this._Orders; }
        set { this._Orders.Assign(value); }
    }
    

创建并运行跨越 Customer-Order 关系的查询

现在可以直接从Order对象访问对象,也可以按相反的顺序访问Customer对象。 客户和订单之间不需要显式联接

使用 Customer 对象访问 Order 对象

  1. 修改Main方法,将下面的代码键入或粘贴到方法中:

    // Query for customers who have placed orders.
    var custQuery =
        from cust in Customers
        where cust.Orders.Any()
        select cust;
    
    foreach (var custObj in custQuery)
    {
        Console.WriteLine("ID={0}, Qty={1}", custObj.CustomerID,
            custObj.Orders.Count);
    }
    
  2. 按 F5 调试应用程序。

    注释

    可以在控制台窗口中通过注释掉 db.Log = Console.Out; 来消除 SQL 代码。

  3. 在控制台窗口中按 Enter 停止调试。

创建数据库的强类型化视图

从数据库的强类型化视图着手要容易得多。 通过强键入 DataContext 对象,无需调用 GetTable。 使用强类型 DataContext 对象时,可以在所有查询中使用强类型表。

在以下步骤中,您将创建 Customers 作为映射到数据库中的 Customers 表的强类型化表。

对 DataContext 对象进行强类型化

  1. 在类声明上方 Customer 添加以下代码。

    public class Northwind : DataContext
    {
        // Table<T> abstracts database details per table/data type.
        public Table<Customer> Customers;
        public Table<Order> Orders;
    
        public Northwind(string connection) : base(connection) { }
    }
    
  2. Main 方法修改为使用强类型化的 DataContext,如下所示:

    // Use a connection string.
    Northwind db = new Northwind(@"C:\linqtest5\northwnd.mdf");
    
    // Query for customers from Seattle.
    var custQuery =
        from cust in db.Customers
        where cust.City == "Seattle"
        select cust;
    
    foreach (var custObj in custQuery)
    {
        Console.WriteLine($"ID={custObj.CustomerID}");
    }
    // Freeze the console window.
    Console.ReadLine();
    
  3. 按 F5 调试应用程序。

    控制台窗口输出为:

    ID=WHITC

  4. 在控制台窗口中按 Enter 停止调试。

后续步骤

下一个演练(演练:操作数据(C#))将演示如何操作数据。 该演练不要求您保存本系列中已经完成的两个演练的结果。

另请参阅