在第二个例子中,我们拥有一个强类型行,并且我们知道FirstName属性是字符串类型。在此,不会出现杂乱的列名,而且也不存在杂乱的对象转换问题。编译器为我们作类型检查,并且我们可以继续进行其它任务而不必担心是否我们已经正确输入了列名。
对于所有其它列也是如此;总之,当你能够使用一个更为具体的类型时,你永远不应该使用一个泛型对象。但是,请等一下。该强类型对象出自何处?我想我能够告诉你这些对象是为你自动创建的。然而,正如要建立良好的关系需要时间和精力一样,强类型化你的对象也需要付出其它努力。好的方面在于,这里所花费的额外时间是值得的,而且节省了将来更多的花在调试上的时间。
存在若干种可以实现强类型化的方法,在本文余下的部分中,我们将讨论怎样在Visual Studio 2005中创建强类型DataSet;当然,还将分析一下这样做的优点和缺点。
三、 在VS 2005中创建强类型DataSet
其实,强类型DataSet是一些提前定义了它们自己的列与表的泛型DataSet,这样编译器已经知道它们将会包含什么内容。不是把你的数据包装为一个"露指手套",一个强类型DataSet恰似一个"手套"。每一个Visual Studio的后续版本会使得强类型化一个DataSet的过程更为容易。在这个示例中,我们将使用来自于SQL Server 2005中的AdventureWorks数据库。这只要简单地执行如下步骤:
1. 打开Visual Studio,然后创建一个新的ASP.NET网站。
2. 在Solution Explorer中,占击以添加一个新项并且选择DataSet,并命名为AdventureWorks.xsd。Visual Studio推荐把这个DataSet文件放到App_Code文件夹下。
3. 这个AdventureWorks.xsd将在设计模式下打开,并且激活"TableAdapter Configuration"向导。现在,仅仅点击一下"Cancel"即可。
4. 定位到Server Explorer工具箱,导航到你的SQL Server 2005数据库和AdventureWorks数据库。(如果你还没有安装AdventureWorks数据库的话,你可以从微软的SQL Server 2005 Samples and Sample Databases下载页面下载它,还有另外的SQL Server 2005示例。)
5. 把SalesOrderHeader和SalesOrderDetail表拖动到你的DataSet设计器窗口。现在,这个窗口应该类似于下面的屏幕快照。注意,对于我们加入的每个表,Visual Studio都创建一个强类型DataTable(该名称是基于原始的表)和一个TableAdapter。这个DataTable为我们定义了每一个列。这个表适配器是我们用来填充这个表的对象。缺省情况下,我们有一个Fill()方法,由它找到表中的每一行。
这个强类型DataSet将返回在这两个表中的所有记录。既然AdventureWorks数据库包含大量的订单信息,那么我们为什么不创建一个更为具体些的查询呢?我们可以把方法添加到我们的TableAdapter对象来检索一个更为具体的表的记录子集。首先,右击SalesOrderHeaderTableAdapter,并且选择"Add|Query"。选择"Use SQL statements"并且点击Next按钮。然后,选择"SELECT which returns rows"并且点击Next按钮。最后,在窗口中输入下列查询(或使用Query Builder来实现相同的任务):
这个SQL查询是一个简单的SELECT查询,它有一个@OrderDate参数以进一步缩小结果范围。这样可以防止我们返回数据库的每一个订单。点选"Fill a DataTable"和"Return a DataTable"复选框,然后点击Finish。在添加这个SELECT语句后,你的设计者现在应该有一个外部查询已经添加到这个SalesOrderHeaderTableAdapter,请参考下面的屏幕快照。
四、 在一个ASP.NET页面上使用强类型DataSet
通过创建强类型DataSet,我们可以仅通过编写几行代码就可以实现容易地在一个ASP.NET页面显示这些数据。首先,在你的网站上创建一个ASP.NET页面并且在设计模式中观察它。然后,拖放一个GridView控件到其上,保持其ID为GridView1。打开ASP.NET页面的源代码并且在文件的顶部导入AdventureWorksTableAdapters命名空间(在C#中,该语法为:"using AdventureWorksTableAdapters;")。最后,把下列代码添加到Page_Load事件处理器中:
这段代码是很简单的。我们创建SalesOrderHeaderTableAdapter的一个实例-我们将使用它来填充DataTable。注意,不是声明一个泛型DataTable,我们声明了一个SalesOrderHeaderDataTable类型的对象。为了填充这个DataTable,我们调用GetDateBy()方法并且传递给它一个DateTime对象。还要注意,甚至这个检索命令也是强类型化的,因为我们必须传递一个DateTime对象,而不仅仅是一个泛型对象。下面的屏幕快照显示了上面示例代码的清晰结果。
除了通过代码把结果绑定到GridView外,你还可以使用一个ObjectDataSource,设置它的TypeName属性为AdventureWorksTableAdapters.SalesOrderHeaderTableAdapter,并且把它的SelectMethod设置为GetData或GetDataBy。
五、 使用强类型DataSet插入、更新和删除数据
在本文中,我们已经看到了怎样使用一个强类型DataSet从一个数据库中选择数据。然而,你还可以使用这些工具来插入、更新和删除基本的数据库数据。
除了不必编写代码来存取数据库外,使用这个强类型化的DataSet的另外一个很大的优点是,在此不存在编译器不能检查的字符串列名潜伏在我们的代码并且我们不必进行任何对象转换。如果我们曾经改变过我们的数据库模式,那么一旦我们更新我们的AdventureWorks.xsd文件,我们将注意到在编译期间的存在于我们的应用程序中的所有的巨大变化。
六、 小结
其实,除了使用强类型DataSet外,还有另外的方法来实现你的应用程序的强类型化。你可以创建定制类-比DataSet更为轻量级并且能够正确地响应于你的数据库。而且,还有一些第三方软件开发者提供工具来自动化这一过程。其中,一个特别的产品是LLBLGen Pro,就是我比较喜欢的工具之一,我还写了有关于它的一本书:《Rapid C# Windows Development: Visual Studio 2005, SQL Server 2005,and LLBLGen Pro》。另外一个流行的工具是CodeSmith。甚至微软也在使用一个与之类似的工具-DLINQ,它仍处于测试阶段,至少在下一年中不会上市。
如果你使用Visual Studio强类型DataSet方法,那么你不需要购买任何另外的软件-这是一个明显的优点。所有这些解决方案都有其各自不同的特征和优点,但是强类型化你的关系数据的主要优点还在于:可靠性,更少的错误和更少的调试时间花费;另外,分析数据库模式变化的影响并实现它们也更为容易。最后,非常希望你已经了解到强类型化的优点。祝你幸运!