视频演示:http://u.115.com/file/f2e338988d
本演练演示如何使用 LINQ to SQL 关联来表示数据库中的外键关系。
此演示是建立在前一个演示的基础上。光脚丫学LINQ(016):[演练]创建简单对象模型和LINQ查询(C#),你可以通过这个链接转到前一个演示。
跨表映射关系
在 Customer 类定义的后面,创建包含如下代码的 Order 实体类定义,这些代码表示 Order.Customer 作为外键与 Customer.CustomerID 相关。
在 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; }
}
}
[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 类中:
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); }
}
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 关系创建并运行查询
现在您可以直接从 Customer 对象访问 Order 对象,或反过来进行访问。 您不需要在客户和订单之间具有显式联接。
使用Customer对象访问Order对象
1、 通过将下面的代码键入或粘贴到 Main 方法中修改此方法:
// Query for customers who have placed orders.
var CustomersHasOrders =
from CustomerObject in Customers
where CustomerObject.Orders.Any()
select CustomerObject;
foreach (var CustomerObject in CustomersHasOrders)
{
Console.WriteLine("ID={0}, Qty={1}",
CustomerObject.CustomerID,
CustomerObject.Orders.Count);
}
// Query for customers who have placed orders.
var CustomersHasOrders =
from CustomerObject in Customers
where CustomerObject.Orders.Any()
select CustomerObject;
foreach (var CustomerObject in CustomersHasOrders)
{
Console.WriteLine("ID={0}, Qty={1}",
CustomerObject.CustomerID,
CustomerObject.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) { }
}
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\Northwind.mdf");
// Query for customers from Seattle.
var SeattleCustomers =
from CustomerObject in db.Customers
where CustomerObject.City == "Seattle"
select CustomerObject;
foreach (var CustomerObject in SeattleCustomers)
{
Console.WriteLine("ID={0}", CustomerObject.CustomerID);
}
// Freeze the console window.
Console.ReadLine();
// Use a connection string.
Northwind db = new Northwind(@"C:\linqtest5\Northwind.mdf");
// Query for customers from Seattle.
var SeattleCustomers =
from CustomerObject in db.Customers
where CustomerObject.City == "Seattle"
select CustomerObject;
foreach (var CustomerObject in SeattleCustomers)
{
Console.WriteLine("ID={0}", CustomerObject.CustomerID);
}
// Freeze the console window.
Console.ReadLine();
完整的演示代码如下:
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Data.Linq.Mapping;
namespace Demo02
{
[Table(Name = "Customers")]
public class Customer
{
private string _CustomerID;
[Column(IsPrimaryKey = true, Storage = "_CustomerID")]
public string CustomerID
{
get
{
return this._CustomerID;
}
set
{
this._CustomerID = value;
}
}
private string _City;
[Column(Storage = "_City")]
public string City
{
get
{
return this._City;
}
set
{
this._City = value;
}
}
private EntitySet<Order> _Orders;
public Customer()
{
this._Orders = new EntitySet<Order>();
}
[Association(Storage = "_Orders", ThisKey = "CustomerID", OtherKey = "CustomerID")]
public EntitySet<Order> Orders
{
get { return this._Orders; }
set { this._Orders.Assign(value); }
}
}
[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", OtherKey = "CustomerID")]
public Customer Customer
{
get { return this._Customer.Entity; }
set { this._Customer.Entity = value; }
}
}
class Program
{
static void Main(string[] args)
{
// *************************************************
// 跨关系查询。
// *************************************************
// Use a connection string.
DataContext db = new DataContext(@"C:\linqtest5\Northwind.mdf");
// Get a typed table to run queries.
Table<Customer> Customers = db.GetTable<Customer>();
// Attach the log to show generated SQL.
//db.Log = Console.Out;
// Query for customers who have placed orders.
var CustomersHasOrders =
from CustomerObject in Customers
where CustomerObject.Orders.Any()
select CustomerObject;
foreach (var CustomerObject in CustomersHasOrders)
{
Console.WriteLine("ID={0}, Qty={1}",
CustomerObject.CustomerID,
CustomerObject.Orders.Count);
//Console.WriteLine(CustomerObject.Orders[0].Customer.CustomerID);
}
// Prevent console window from closing.
Console.ReadLine();
// *************************************************
// 使用强类型的数据上下文。
// *************************************************
// Use a connection string.
//Northwind db = new Northwind(@"C:\linqtest5\Northwind.mdf");
Query for customers from Seattle.
//var SeattleCustomers =
// from CustomerObject in db.Customers
// where CustomerObject.City == "Seattle"
// select CustomerObject;
//foreach (var CustomerObject in SeattleCustomers)
//{
// Console.WriteLine("ID={0}", CustomerObject.CustomerID);
//}
Freeze the console window.
//Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Data.Linq.Mapping;
namespace Demo02
{
[Table(Name = "Customers")]
public class Customer
{
private string _CustomerID;
[Column(IsPrimaryKey = true, Storage = "_CustomerID")]
public string CustomerID
{
get
{
return this._CustomerID;
}
set
{
this._CustomerID = value;
}
}
private string _City;
[Column(Storage = "_City")]
public string City
{
get
{
return this._City;
}
set
{
this._City = value;
}
}
private EntitySet<Order> _Orders;
public Customer()
{
this._Orders = new EntitySet<Order>();
}
[Association(Storage = "_Orders", ThisKey = "CustomerID", OtherKey = "CustomerID")]
public EntitySet<Order> Orders
{
get { return this._Orders; }
set { this._Orders.Assign(value); }
}
}
[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", OtherKey = "CustomerID")]
public Customer Customer
{
get { return this._Customer.Entity; }
set { this._Customer.Entity = value; }
}
}
class Program
{
static void Main(string[] args)
{
// *************************************************
// 跨关系查询。
// *************************************************
// Use a connection string.
DataContext db = new DataContext(@"C:\linqtest5\Northwind.mdf");
// Get a typed table to run queries.
Table<Customer> Customers = db.GetTable<Customer>();
// Attach the log to show generated SQL.
//db.Log = Console.Out;
// Query for customers who have placed orders.
var CustomersHasOrders =
from CustomerObject in Customers
where CustomerObject.Orders.Any()
select CustomerObject;
foreach (var CustomerObject in CustomersHasOrders)
{
Console.WriteLine("ID={0}, Qty={1}",
CustomerObject.CustomerID,
CustomerObject.Orders.Count);
//Console.WriteLine(CustomerObject.Orders[0].Customer.CustomerID);
}
// Prevent console window from closing.
Console.ReadLine();
// *************************************************
// 使用强类型的数据上下文。
// *************************************************
// Use a connection string.
//Northwind db = new Northwind(@"C:\linqtest5\Northwind.mdf");
Query for customers from Seattle.
//var SeattleCustomers =
// from CustomerObject in db.Customers
// where CustomerObject.City == "Seattle"
// select CustomerObject;
//foreach (var CustomerObject in SeattleCustomers)
//{
// Console.WriteLine("ID={0}", CustomerObject.CustomerID);
//}
Freeze the console window.
//Console.ReadLine();
}
}
}
Northwind.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
namespace Demo02
{
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) { }
}
}