为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模式一节详细介绍了这个方法。 |