为 DataTable 创建模式有 3 种方式:
● 让运行库来完成
● 编写代码来创建表
● 使用 XML 模式生成器
(1) 运行 库 生成的模式
前面的 DataRow 示例用下面的代码从数据库中选择数据,并生成一个 DataSet :
SqlDataAdapter da = new SqlDataAdapter(select , conn);
DataSet ds = new DataSet();
da.Fill(ds , "Customers");
这是很容易使用的,但也有几个缺点。例如,必须利用默认的列名来处理—— 这是可以的,但在某些情况下,还要把物理数据库的列 ( 如 PKID) 重新命名为一个用户友好性更高的名称。
自然,可以在 SQL 子句中重新给列指定别名,例如 SELECT PID AS PersonID FROM PersonTable 。最好不要在 SQL 中重新给列命名,因为列实际上只需要在屏幕上显示一个“比较好”的名称即可。
自动生成 DataTable/DataColumn 的另一个潜在的问题是不能控制运行库为列选择的数据类型。运行库可以确定正确的数据类型,但有时需要对此有更多的控制。例如,为给定的列定义枚举类型,以简化类的用户代码。如果接受运行库生成的默认列类型,该列就可能是一个 32 位的整数,而不是有预定选项的枚举。
最后,也是最有可能出的问题是,在使用自动生成的表时,不能对 DataTable 中的数据进行类型安全的访问—— 索引器就会返回 object 的实例,而不是派生的数据类型。如果要用代码对表达式进行类型转换,就可以跳过下面的章节。
(2) 手工编码的模式
用生成代码来创建 DataTable , 再用相关的 DataColumns 来填充是相当简单的。本节的示例将访问 Northwind 数据库中的 Product 表 , 如图 21-6 所示。
图 21-6
下面的代码生成了一个 DataTable ,对应于上面的模式 ( 但没有包含可为空的列 ) :
public static void ManufactureProductDataTable(DataSet ds)
{
DataTable products = new DataTable("Products");
products.Columns.Add(new DataColumn("ProductID", typeof(int)));
products.Columns.Add(new DataColumn("ProductName", typeof(string)));
products.Columns.Add(new DataColumn("SupplierID", typeof(int)));
products.Columns.Add(new DataColumn("CategoryID", typeof(int)));
products.Columns.Add(new DataColumn("QuantityPerUnit", typeof(string)));
products.Columns.Add(new DataColumn("UnitPrice", typeof(decimal)));
products.Columns.Add(new DataColumn("UnitsInStock", typeof(short)));
products.Columns.Add(new DataColumn("UnitsOnOrder", typeof(short)));
products.Columns.Add(new DataColumn("ReorderLevel", typeof(short)));
products.Columns.Add(new DataColumn("Discontinued", typeof(bool)));
ds.Tables.Add(products);
}
可以改变 DataRow 示例中的代码,使用新生成的表定义:
string source = "server=(local)//NetSDK;" +
"integrated security=sspi;" +
"database=Northwind";
string select = "SELECT * FROM Products";
SqlConnection conn = new SqlConnection(source);
SqlDataAdapter cmd = new SqlDataAdapter(select, conn);
DataSet ds = new DataSet();
ManufactureProductDataTable(ds);
cmd.Fill(ds, "Products");
foreach(DataRow row in ds.Tables["Products"].Rows)
Console.WriteLine("'{0}' from {1}", row[0], row[1]);
ManufactureProductDataTable 方法创建一个新 DataTable ,依次添加每个列,最后把这个表添加到 DataSet 中表的清单上。 DataSet 有一个索引器,它的参数是表名,给调用者返回该 DataTable 。
上面的示例仍不是类型安全的,因为在列上使用了索引器来检索数据。最好是有一个类 ( 或一组类 ) 派生于 DataSet 、 DataTable 和 DataRow ,为表、行和列定义类型安全的存取器。可以自己生成这段代码,这并不是特别乏味,最终将得到可以进行类型安全访问的类。
如果不愿意自己生成这些类型安全的类,可以使用帮助。 .NET Framework 允许使用 XML 模式来定义 DataSet 、 DataTables 和本节介绍的其他类。本章后面的 XML 模式一节详细介绍了这个方法。