DataGridView顯示主從表示例及注意事項

原創文章·轉載請註明來源:http://blog.csdn.net/hulihui)

 

 

在.NET的Windows Forms數據處理應用中,經常需要處理主從表情況。例如:SQL Server 2000的Northwind數據庫Custumers表和Orders表中,一個客戶對應多個定單(用關係數據庫理論的ER概念模型描述,客戶實體與定單實體是1:N的關係)。編程時,可以用一個DataGridView顯示Customers記錄(主表),另一個DataGridView顯示當前Customer的定單明細(從表)。當點選主表DataGridView的Customers記錄時,從表DataGridView自動過濾顯示對應CustomerID的全部Orders記錄(見上圖)。C# 2005/2008中的BindingSource組件和DataSet/DataRelation類提供了一個簡便的處理方法,見如下實現步驟和示例代碼。

  1. 建立一個DataSet數據集對象,使用DataAdaper填充兩個DataTable表:Customers和Orders,分別包含全部的Customers記錄和Orders記錄。此外,也可直接創建和填充合適的數據表,參見文後附加的代碼;
  2. 以Custumers的主鍵CustomerID和Orders的外鍵CustomerIdD建立一個主從DataRelation關係對象,並添加該對象到DataSet中;
  3. 使用兩個BindingSource組件:bs_Customers和bs_Orders,分別連接表數據集DataSet的表Customers和關係DataRelation。該步是實現主從表的關鍵技巧;
  4. 使用兩個DataGridView組件,分別連接bs_Customers和bs_Orders。

下面是全部程序示例代碼(提示:Form1上必須有兩個DataGridView控件,即DataGridView1和DataGridView2),測試運行時須有SQL Server 2000的Northwind數據庫,不使用數據庫且直接創建數據表的代碼參見本文最後給出的簡例。

using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;

namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection();
SqlConnectionStringBuilder ssb = new SqlConnectionStringBuilder();
conn.ConnectionString =
"Data Source=localhost; Initial Catalog=Northwind; Integrated Security = True;";
conn.Open();

DataSet dbSet = new DataSet(); // 創建數據集
using (SqlDataAdapter da = new SqlDataAdapter("select * from Customers", conn))
{
da.Fill(dbSet, "Customers"); // 填充一個 Customers 表
}
using (SqlDataAdapter da = new SqlDataAdapter("select * from Orders", conn))
{
da.Fill(dbSet, "Orders"); // 填充一個 Orders 表
}

// ##說明:上面是Northwind庫表創建程序,文後附加的代碼可以取代上述功能

DataColumn parentCol = dbSet.Tables["Customers"].Columns["CustomerID"];
DataColumn childCol = dbSet.Tables["Orders"].Columns["CustomerID"];
DataRelation relation =
new DataRelation("FK_Customers_Orders", parentCol, childCol); // 建立主從關係
dbSet.Relations.Add(relation); // 添加主從關係到數據集中

BindingSource bs_Customers = new BindingSource(); // 創建綁定源
BindingSource bs_Orders = new BindingSource();

bs_Customers.DataSource = dbSet;
bs_Customers.DataMember = "Customers"; // 綁定到數據源——主表

bs_Orders.DataSource = bs_Customers;
bs_Orders.DataMember = "FK_Customers_Orders"; // 綁定到關係——從表,注意:區分大小寫

dataGridView1.DataSource = bs_Customers; // DataGridView 顯示
dataGridView2.DataSource = bs_Orders;
}
}
}

與主表的常規綁定方式不同,從表bs_Orders的數據源和數據成員的綁定技巧是:

  • bs_Orders.DataSource = bs_Customers,即主表的BindingSource數據源;
  • bs_Orders.DataMember = "FK_Customers_Orders",即數據集dsSet中的主從關係名。

特別需要指出:當使用C#2005/2008編程時,從表bs_Orders的數據成員DataMember使用的關係名是區分大小寫的。針對上面示例,如果代碼改爲:DataMember = "fk_Customers_Orders",即修改"FK"爲"fk",此時程序並不報錯,並且主表第一條記錄對應的從表記錄是正確的!但瀏覽移動主表記錄時,從表對應的記錄爲空,即使主表移動到第一條記錄時從表也爲空!

 

同時還需要指出如下幾點:

  • 並不要求CustomerID是Customers的主鍵和Orders的外鍵,但要滿足外鍵的基本條件——主表的CustomerID值唯一,從表的CustomerID值對應主表的某個值。見本文後面給出的程序代碼;
  • 主從關係是通過數據集DataSet、數據關係DataRelation和數據源綁定組件BindingSource體現的,與顯示控件無關。此時,可以使用ComboBox、ListBox等顯示主從關係情況;
  • 主從關係中的數據表,還可以是定製的對象集,具體使用可以參考《Windows Forms 2.0數據綁定——.NET智能客戶端數據應用程序設計》一書。

事實上,.NET通過字符串名稱檢索是其特性——索引器,即通過[]設置和訪問對象,許多情況並不區分大小寫,如:DataSet.Table[]、DataGridViewColumns[]、BindingSource.DataMember(爲數據表時)。爲何C# 2005/2008中DataRelation的關係名區分大小寫?或者是否是.NET的一個BUG?有興趣者可以進一步探討。

 

下面是直接構建兩個表的代碼,取代前面創建數據庫連接和從Northwind填充數據的兩個using(){}語句組:

private void Form1_Load(object sender, EventArgs e)
{
DataSet dbSet = new DataSet(); // 創建數據集

DataTable customers = new DataTable("Customers"); // 創建客戶表
DataColumn dc = new DataColumn("CustomerID", typeof(int)); // 創建字段
customers.Columns.Add(dc);
customers.Rows.Add(1); // 添加兩個記錄
customers.Rows.Add(2);

DataTable orders = new DataTable("Orders"); // 創建定單表
dc = new DataColumn("OrderId", typeof(int));
orders.Columns.Add(dc);
dc = new DataColumn("CustomerID", typeof(int));
orders.Columns.Add(dc);

orders.Rows.Add(1, 1); // 添加記錄,注意:CustomerID必須與前面表的某個值相同
orders.Rows.Add(2, 1); // 即要滿足外鍵的條件
orders.Rows.Add(3, 2);
orders.Rows.Add(4, 2);

dbSet.Tables.Add(customers);
dbSet.Tables.Add(orders);

// 接前面的 ##說明 後面的代碼部分,即創建關係、綁定數據源等
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章