Chương 8 Ứng dụng Windows với WindowsForm
9.8.3. Kết hợp giữa nhiều bảng
Các ví dụ ở trên chỉđơn thuần lấy dữ liệu từ trong một bảng. Ở ví dụ này ta sẽ
hàng có thể có nhiều hóa đơn khác nhau, vì thế ta sẽ có quan hệ một nhiều giữa bảng khách hàng (Customers) và bảng hóa đơn (Orders). Bảng Orders sẽ chứa thuộc tính CustomersId của bảng Customers, thuộc tính này đóng vai trò là khóa chính đối bảng Customers và khóa ngoại đối với bảng Orders.
Ứng dụng của ta sẽ hiển thị dữ liệu của hai bảng Customers và Orders trên cùng một lưới và thể hiện quan hệ một nhiều của hai bảng ngay trên lưới. Để làm
được điều này ta chỉ cần dùng chung một đối tượng Connetion, hai đối tượng tượng SqlDataAdapter và hai đối tượng SqlCommand.
Sau khi tạo đối tượng SqlDataAdapter cho bảng Customers tương tự như ví dụ
trên, ta tiến tạo tiếp đối tượng SqlDataAdapter cho bảng Orders : myCommand2 = new System.Data.SqlClient.SqlCommand(); DataAdapter2 = new System.Data.SqlClient.SqlDataAdapter(); myCommand2.Connection = myConnection;
myCommand2.CommandText = "SELECT * FROM Orders";
Lưu ý là ở đây đối tượng DataAdapter2 có thể dùng chung đối tượng Connection ở trên, nhưng đối tượng Command thì khác. Sau đó gắn đối tượng Command2 cho DataAdapter2, ánh xạ bảng dữ liệu và đẩy dữ liệu vào DataSet ở
trên.
DataAdapter2.SelectCommand = myCommand2;
DataAdapter2.TableMappings.Add ("Table", "Orders"); DataAdapter2.Fill(myDataSet);
Tại thời điểm này, ta có một đối tượng DataSet nhưng chứa hai bảng dữ liệu : Customers và Orders. Do ta cần thể hiện cả quan hệ của hai bảng ngay trên
điều khiển lưới, cho nên ta cần phải định nghĩa quan hệ này cho đối tượng DataSet của chúng ta. Nếu không làm điều này thì đối tượng DataSet sẽ bỏ qua quan hệ
giữa 2 bảng này.
Do đó ta cần khai báo thêm đối tương DataRelation: System.Data.DataRelation dataRelation;
Do mỗi bảng Customers và Orders đều có chứa một thuộc tính CustomersId, nên ta cũng cần khái báo thêm hai đối tượng DataColumn tương ứng với hai thuộc tính này.
System.Data.DataColumn dataColumn1; System.Data.DataColumn dataColumn2;
Mỗi một DataColumn sẽ giữ giá trị của một cột trong bảng của đối tượng DataSet :
dataColumn1 = myDataSet.Tables["Customers"].Columns["CustomerID"]; dataColumn2 = myDataSet.Tables["Orders"].Columns["CustomerID"];
Ta tiến hành tạo quan hệ cho hai bảng bằng cách gọi hàm khởi tạo của đối tượng DataRelation, truyền vào cho nó tên quan hệ và hai cột cần tạo quan hệ :
dataRelation = new System.Data.DataRelation("CustomersToOrders", dataColumn1, dataColumn2);
ta cần tạo một đối tượng quản lý khung nhìn DataViewManager cho DataSet, đối tượng khung nhìn này sẽđược gán cho lưới điều khiển để hiển thị:
myDataSet.Relations.Add(dataRelation);
DataViewManager DataSetView = myDataSet.DefaultViewManager; dataGrid1.DataSource = DataSetView;
Do điều khiển lưới phải hiển thị quan hệ của hai bảng dữ liệu, nên ta phải chỉ
cho nó biết là bảng nào sẽ là bảng cha. Ởđây bảng cha là bảng Customers: dataGrid1.DataMember= "Customers";
Sau đây là mã hoàn chỉnh của toàn bộứng dụng: using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Data.SqlClient; namespace ProgrammingCSharpWindows.Form {
public class ADOForm1: System.Windows.Forms.Form {
private System.ComponentModel.Container components; private System.Windows.Forms.DataGrid dataGrid1;
private System.Data.SqlClient.SqlConnection myConnection; private System.Data.DataSet myDataSet;
private System.Data.SqlClient.SqlCommand myCommand; private System.Data.SqlClient.SqlCommand myCommand2; private System.Data.SqlClient.SqlDataAdapter DataAdapter; private System.Data.SqlClient.SqlDataAdapter DataAdapter2; public ADOForm1( )
{
InitializeComponent( ); // tạo kết nối
string connectionString = "server=Neptune; uid=sa;" + " pwd=oWenmEany; database=northwind";
myConnection = new SqlConnection(connectionString); myConnection.Open( );
// tạo DataSet
myDataSet = new System.Data.DataSet( );
// tạo đối tượng Command và DataSet cho bảng Customers myCommand = new System.Data.SqlClient.SqlCommand( ); myCommand.Connection=myConnection;
DataAdapter =new System.Data.SqlClient.SqlDataAdapter(); DataAdapter.SelectCommand= myCommand;
DataAdapter.TableMappings.Add("Table","Customers"); DataAdapter.Fill(myDataSet);
// tạo đối tượng Command và DataSet cho bảng Orders
myCommand2 = new System.Data.SqlClient.SqlCommand( ); DataAdapter2 = new System.Data.SqlClient.SqlDataAdapter(); myCommand2.Connection = myConnection;
myCommand2.CommandText = "SELECT * FROM Orders"; DataAdapter2.SelectCommand = myCommand2;
DataAdapter2.TableMappings.Add ("Table", "Orders"); DataAdapter2.Fill(myDataSet);
// thiết lập quan hệ giữa 2 bảng
System.Data.DataRelation dataRelation; System.Data.DataColumn dataColumn1; System.Data.DataColumn dataColumn2;
dataColumn1 = myDataSet.Tables["Customers"].Columns["CustomerID"]; dataColumn2 = myDataSet.Tables["Orders"].Columns["CustomerID"]; dataRelation = new System.Data.DataRelation
("CustomersToOrders", dataColumn1, dataColumn2); // thêm quan hệ trên vào DataSet
myDataSet.Relations.Add(dataRelation);
// Đặt khung nhìn và bảng hiển thị trước cho lưới
DataViewManager DataSetView = myDataSet.DefaultViewManager; dataGrid1.DataSource = DataSetView;
dataGrid1.DataMember= "Customers"; }
public override void Dispose( ) {
base.Dispose( );
components.Dispose( ); }
private void InitializeComponent( ) {
this.components = new System.ComponentModel.Container(); this.dataGrid1 = new System.Windows.Forms.DataGrid(); dataGrid1.BeginInit( );
dataGrid1.Location = new System.Drawing.Point(24, 32); dataGrid1.Size = new System.Drawing.Size(480, 408); dataGrid1.DataMember = "";
dataGrid1.TabIndex = 0; this.Text = "ADOFrm1";
this.ClientSize = new System.Drawing.Size (536, 501); this.Controls.Add (this.dataGrid1); dataGrid1.EndInit ( ); }
public static void Main(string[] args) {
Application.Run(new ADOForm1( )); }
} }
Khi chạy ứng dụng sẽ có giao diện nhu sau:
Hình 9-6 Quan hệ một nhiều giữa hai bảng Customers và Orders
Hình 9-7 Danh sách các hóa đơn tương ứng với khách hàng được chọn