Hơn thế nữa, bạn có thể định nghĩa một DataSet, với một số DataTables, một bộ các quan hệ giữa các bảng, bao gồm các chi tiết và mô tả đây đủ của dữ liệu.. Khi bạn có một file XSD, có mộ
Trang 1Các Sơ đồ XML
XML là một đường hào vững chắc bao bọc ADO.NET - thật vậy, các định dạng điều khiển cho việc truyền dữ liệu hiện tại là XML Với thời gian chạy NET, nó có thể mô tả một DataTable trong một file sơ đồ XML Hơn thế nữa, bạn có thể định nghĩa một
DataSet, với một số DataTables, một bộ các quan hệ giữa các bảng, bao gồm các chi tiết
và mô tả đây đủ của dữ liệu
Khi bạn có một file XSD, có một công cụ trong thời gian chạy để chuyển sơ đồ này thành các lớp dữ liệu tương ứng, chẳng hạn như một lớp DataTable ở trên Trong phần này chúng ta sẽ bắt đầu với một file XSD đơn giản dùng để mô tả các thông tin tương tự ví dụ Products ở trên, và sau đó tạo ra một vài tính năng mở rộng File này là Products.xsd, trong thư mục 10_XSD_DataSet:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema
id="Products"
targetNamespace="http://tempuri.org/XMLSchema1.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema1.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema1.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Product">
<xs:complexType>
<xs:sequence>
<xs:element name="ProductID" type="xs:int" />
<xs:element name="ProductName" type="xs:string" />
<xs:element name="SupplierID" type="xs:int" minOccurs="0" />
<xs:element name="CategoryID" type="xs:int" minOccurs="0" />
<xs:element name="QuantityPerUnit" type="xs:string" minOccurs="0" />
<xs:element name="UnitPrice" type="xs:decimal" minOccurs="0" />
<xs:element name="UnitsInStock" type="xs:short" minOccurs="0" />
<xs:element name="UnitsOnOrder" type="xs:short" minOccurs="0" />
<xs:element name="ReorderLevel" type="xs:short" minOccurs="0" />
<xs:element name="Discontinued" type="xs:boolean" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Trang 2Chúng ta sẽ xem xét kĩ trong chương 11; còn bây giờ, file này cơ bản định nghĩa mọt sơ
đồ với các thuộc tính id tạo thành Products Một kiểu phức tạp Product đã được định nghĩa, để chứa một số các yếu tố, cho mỗi trường trong bảng Products
Cảm ơn NET Framework đã công cụ XSD.EXE để tạo ra tất cả các mã cho các lớp này chỉ cần một file nhập XSD
Tạo mã với XSD
Bạnc có thể lưu file trên với tên Product.xsd, và chuyển nó thành mã với lệnh sau:
xsd Product.xsd /d
Nó sẽ tạo ra file Product.cs
Có một vài cách có thể dùng XSD để thay đổi output generated Một vài cách phổ biến được đưa ra trong bảng sau
Switch Description
/dataset (/d) Các lớp được thừa kế từ DataSet, DataTable, và DataRow /language:<language> Cho phép bạn chon ngôn ngữ để chuyển C# là giá trị mặc
định, nhưng có thể chọn VB cho một file Visual Basic .NET
/namespace:<namespace> Định nghĩa không gian tên của code được phát ra Giá trị
mặc định là no namespace
Một phiên bản ngắn gọn của XSD cho sơ đồ Products được trình bày dưới đây Tôi đã bỏ
đi môt vài mã không cần thiết chỉ giữ lại những gì quan trọng nhất, và làm một vài thao tác định dạng lại để vừa với khổ giấy Để xem kết quả cuối cùng, chạy XSD.EXE trên sơ
đồ Products và xem xet file cs được tạo ra Mã ví dụ trong thư mục 10_XSD_DataSet: // -
// <autogenerated>
// This code was generated by a tool
// Runtime Version: 1.0.3512.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated
// </autogenerated>
// -
//
Trang 3// This source code was auto-generated by xsd, Version=1.0.3512.0
//
using System;
using System.Data;
using System.Xml;
using System.Runtime.Serialization;
[Serializable()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Diagnostics.DebuggerStepThrough()]
[System.ComponentModel.ToolboxItem(true)]
public class Products : DataSet
{
private ProductDataTable tableProduct;
public Products()
public ProductDataTable Product
public override DataSet Clone()
public delegate void ProductRowChangeEventHandler ( object sender,
ProductRowChangeEvent e);
[System.Diagnostics.DebuggerStepThrough()]
public class ProductDataTable : DataTable, System.Collections.IEnumerable
[System.Diagnostics.DebuggerStepThrough()]
public class ProductRow : DataRow
}
Tôi đã hơi tùy tiện trong mã này, tôi đã tách nó thành 3 phần và bỏ đi các thành phần protected và private vì vậy chúng ta chỉ có thể tập trung vào các giao diện chính Chúng
ta sẽ xem xét mã sau trong phần nó về DataSet
Cấu trúc của Products() gọi một phương thức tĩnh, InitClass(), nó xây dựng một thể hiện của lớp ProductDataTable xuất phát từ lớp DataTable, và thêm nó vào tập hợp các Tables của DataSet Bảng dữ liệu Products có thể được truy cập như mã dưới đây:
DataSet ds = new Products();
DataTable products = ds.Tables["Products"];
Hoặc, đơn giản hơn bằng cách sử dụng thuộc tính Product, sẵn có trong các đối tượng xuất phát từ DataSet:
DataTable products = ds.Product;
Trang 4Lớp ProductDataTable bao gồm các mã khác như sau:
[System.Diagnostics.DebuggerStepThrough()]
public class ProductDataTable : DataTable, System.Collections.IEnumerable
{
private DataColumn columnProductID;
private DataColumn columnProductName;
private DataColumn columnSupplierID;
private DataColumn columnCategoryID;
private DataColumn columnQuantityPerUnit;
private DataColumn columnUnitPrice;
private DataColumn columnUnitsInStock;
private DataColumn columnUnitsOnOrder;
private DataColumn columnReorderLevel;
private DataColumn columnDiscontinued;
internal ProductDataTable() : base("Product")
{
this.InitClass();
}
Lớp ProductDataTable, được xuất phát từ DataTable và thực thi giao diện IEnumerable, định nghĩa một thể hiện DataColumn tĩnh cho mỗi cột trong bảng Chúng được khởi động một lần nữa từ cấu tử bởi việc gọi phương thức tĩnh InitClass() Mỗi cột cung cấp một con trỏ nội, lớp DataRow được mô tả sau
[System.ComponentModel.Browsable(false)]
public int Count
{
get { return this.Rows.Count; }
}
internal DataColumn ProductIDColumn
{
get { return this.columnProductID; }
}
// Other row accessors removed for clarity - there is one for each of the columns
Việc thêm các dòng vào bảng được cung cấp bởi hai quá tải trong phương thức
AddProductRow() Quá tải thứ nhất tạo DataRow và không trả về giá trị nào cả Quá tải thứ hai là một tập các giá trị, mỗi giá trị dành cho các cột trong DataTable, tạo các giá trị cho một dòng mới, thêm dòng vào DataTable và trả dòng về cho trình gọi
public void AddProductRow(ProductRow row)
Trang 5{
this.Rows.Add(row);
}
public ProductRow AddProductRow ( string ProductName , int SupplierID ,
int CategoryID , string QuantityPerUnit ,
System.Decimal UnitPrice , short UnitsInStock ,
short UnitsOnOrder , short ReorderLevel ,
bool Discontinued )
{
ProductRow rowProductRow = ((ProductRow)(this.NewRow()));
rowProductRow.ItemArray = new object[]
{
null,
ProductName,
SupplierID,
CategoryID,
QuantityPerUnit,
UnitPrice,
UnitsInStock,
UnitsOnOrder,
ReorderLevel,
Discontinued
};
this.Rows.Add(rowProductRow);
return rowProductRow;
}
Giống như thành phần InitClass() trong lớp xuất phát từ DataSet, dùng để thêm bảng vào trong DataSet, thành phần InitClass() trong ProductDataTable thêm các cột vào
DataTable Thuộc tính của mỗi cột được điền thích hợp, và cột sau đó được thêm vào tập hợp columns
private void InitClass()
{
this.columnProductID = new DataColumn ( "ProductID",
typeof(int),
null,
System.Data.MappingType.Element);
this.Columns.Add(this.columnProductID);
// Other columns removed for clarity
this.columnProductID.AutoIncrement = true;
Trang 6this.columnProductID.AllowDBNull = false;
this.columnProductID.ReadOnly = true;
this.columnProductName.AllowDBNull = false;
this.columnDiscontinued.AllowDBNull = false;
}
public ProductRow NewProductRow()
{
return ((ProductRow)(this.NewRow()));
}
Phương thức cuối cùng mà tôi muốn nói tới, NewRowFromBuilder(), được gọi trực tiếp
từ phương thức NewRow() của DataTable Ở đây nó tạo một dòng định kiểu mạnh Thể hiện của DataRowBuilder được tạo bởi DataTable, các thành phần của nó chỉ có thể truy
sử dụng trong nhị phân System.Data
protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
{
return new ProductRow(builder);
}
Và lớp cuối cùng được nói tới là ProductRow xuất phát từ DataRow Lớp này được dùng
để cung cấp cách truy cập bảo vệ kiểu cho tất cả các trường của dữ liệu trong bảng dữ liệu Nó là một bao một dòng riêng và cung các các thành phần cót thể đọc và viết cho các cột trong bảng
Các vùng khả rỗng sẽ được kiểm tra kĩ lưỡng Ví dụ dưới đây chỉ ra các khả năng của cột SupplierID:
[System.Diagnostics.DebuggerStepThrough()]
public class ProductRow : DataRow
{
private ProductDataTable tableProduct;
internal ProductRow(DataRowBuilder rb) : base(rb)
{
this.tableProduct = ((ProductDataTable)(this.Table));
}
public int ProductID
{
get { return ((int)(this[this.tableProduct.ProductIDColumn])); }
set { this[this.tableProduct.ProductIDColumn] = value; }
Trang 7}
// Other column accessors/mutators removed for clarity
public bool IsSupplierIDNull()
{
return this.IsNull(this.tableProduct.SupplierIDColumn);
}
public void SetSupplierIDNull()
{
this[this.tableProduct.SupplierIDColumn] = System.Convert.DBNull;
}
}
Giờ đây chúng ta có thể kết hợp các lớp được sinh ra bởi XSD.EXE vào mã nguồn Mã dưới đây sử dụng các lớp để nhận dữ liệu từ bảng Products và thể hiện ra màn hình
console:
using System;
using System.Data;
using System.Data.SqlClient;
public class XSD_DataSet
{
public static void Main()
{
string source = "server=(local)\\NetSDK;" +
"uid=QSUser;pwd=QSPassword;" +
"database=northwind";
string select = "SELECT * FROM Products";
SqlConnection conn = new SqlConnection(source);
SqlDataAdapter da = new SqlDataAdapter(select , conn);
Products ds = new Products();
da.Fill(ds , "Product");
foreach(Products.ProductRow row in ds.Product )
Console.WriteLine("'{0}' from {1}" ,
row.ProductID ,
row.ProductName);
}
}
Các phần chính được bôi đậm Mã trên chứa một lớp Products xuất phát từ DataSet, được tạo và điền dữ liệu bởi trình cung cấp dữ liệu
Trang 8Để biên dịch ví dụ này bạn dùng lệnh sau:
xsd product.xsd /d
và
csc /recurse:*.cs
Dòng đầu tiên tạo ra file Products.cs từ sơ đồ Products.XSD, và dòng thứ hại sử dụng tham số /recurse:*.cs để duyệt tất cả các file trong extension cs và thêm vào nhị phân cuối