数据库-ADONET-使用强类型DataSet

 

使用强类型DataSet对象

使用ADONET访问DataSet内容的方式,与使用ADODAORecordset对象具有类似的编程格式。

ADONETVBNET

txtCompanyName.Text=ds.Tables(“Customers”).Row(0)(“CompanyName”)

ADODAPVB经典方式

txtCompanyName.Text=rs.Fields(“CompayName”).Value

为了更容易的编写数据访问代码,ADONET引入了强类型DataSet对象。现在可以如下编码

       txtCompanyName.Text=ds.Customers(0).CompanyName

可以把强类型DataSet认作是一个带有类的DataSet,它是继承自DataSet类的一个子类,并且还包含基于你所指定的架构的属性和方法,同时该类还包含用于DataTable对象及DataRow对象的其他类,这些类可以更高效的编写数据访问代码。

1          创建强类型DataSet对象

如何创建一个强类型DataSet

有两种办法:其一,使用代码编写并使用NET框架的SDK命令行工具;其二,使用VSNET开发环境。

1.1         使用命令行工具编写代码

NET框架SDK有一个名为XML架构定义工具的命令行使用工具,它能根据XML架构文件(.xsd)生成类文件。

使用这个使用工具,结合DataSetWriteXmlSchema方法,可以将一个Dataset解析成强类型DataSet类。

1.1.1   使用DataSet对象的WriteXmlSchema方法

XSD文件包含DataSet的架构信息(表、列、约束和关系)。

使用DataSet对象的WriteXmlSchema方法能够创建该文件。

WriteXmlSchema方法,其重载版本能接受,一个Stream对象、一个TextWriter对象、一个XmlWrite对象或字符串表示的文件名。

代码演示:用Northwind数据库的CustomersOrders表的列创建一个DataSet,在将DataSet的架构写入文件之前,为两表添加DataRelation

Dim strConn,strSql as string

strConn=”Providor=SQLOLEDB;Data Source=...;Initial Catalog=Northwind;
Trused_Connection=Yes”

Dim cn As New oleDbConnection(strConn)

strSql=”select CustomerID,CompanyName,ContactName,Phone from Customers”

Dim daCustomers as New oleDBDataAdapter(strSql,cn)

strSql=”select OrderID,CustomerID,EmployeeID,OrderID from Orders”

Dim daOrders as New OleDbDataAdapter(strSql,cn)

Dim ds as new DataSet()

Ds.DataSetName=”Chapter9”

Cn.Open()

daCustomers.FillSchema(ds,SchemaType.Source,”Customers”)

daOrders.FillSchema(ds,SchemaType.Source,”Orders”)

cn.Close()

ds.Relations.Add(“CustomersOrders”,ds.Tables(“Customers”).Columns(“CustomerID”),

ds.Tables(“Orders”).Columns(“CustomerID”))

ds.WriteXmlSchema(“C:"Chapter9.xsd”

1.1.2   使用XML架构定义工具

XML架构定义工具,实际上是指位于Bin目录下的XSD.exe文件,它可以根据XML架构文件生成类文件,还能从Dll文件和EXE文件创建XML架构

示例

前面的代码将DataSet架构保存到Chapter9.xsd文件之中,现在在这个基础上使用XML架构定义工具生成一个类文件。

1.开始菜单,NET Framework v2.0SDK命令提示,

2.对于VBNET输入,XSD Chapter9.xsd /d /l:VB

3.对于C#输入,XSD Chapter9.xsd /d

第一个参数指明XSD文件的路径

第二个参数,指明要创建的类由DataSet派生

第三个参数,指明输出文件语言(默认是C#

使用时,只需要将新类文件加入“解决方案”,并创建新DataSet类的实例:

Dim ds As New Chapter9()

【类的名字】是基于产生XSD文件的DataSet的名字得来的。

1.2         简单的方法(使用IDE

创建过程描述:

首先,创建一个所选语言的新Windows应用程序,将OleDBDataAdapter添加到窗体,在适配器向导中,将OleDBDataAdapter指向Northwind数据库,并输入以下语句:

     Select CustomerID,CompanyName,ContactName,Phone from Customers

     Select OrderID,CustomerID,EmployeeID,OrderDate from Orders

在设计器右键菜单中选择“生成数据集”,输入名字“Chapter9”。

下面设计DataRelation,在“解决方案”窗口,双击架构文件,右键单击Orders表,在菜单中选择“添加”|“新关系”,编辑好关系后确定。

显示类文件

在解决方案窗口顶部,工具栏中选择“显示所有文件”按钮即可。

 

DataSetChapter9.xsd)的架构文件会有两个与该架构文件相关联的文件。第一个是Chapter9.vb或者Chapter9.cs的强类型DataSet类文件;第二个关联文件扩展名为.xsx,它是包含了对XML架构设计器中DataSet的布局进行设置的文本文件。

实际上,该类文件包含许多类。由DataSet派生出来的是主类,这个类公开了两个DataTable对象,分别对应CustomersOrders,而两个DataTable都公开了Item属性,用来返回有DataRow派生出来的子类。

2          使用强类型DataSet对象

强类型DataSet对象简化了开发过程;使编写代码来访问和修改DataSet的内容更加容易。

2.1         添加行

DataSet中的DataTable,每个类都有两种途径——将一个新行添加到DataTable中。

其一:使用New《表名》Row方法,在返回的强类型DataRow中设置列内容,然后调用
Add
《表名》Row添加到表。

        Dim ds As New Chapter9()

        Dim tblCustomers As Chapter9.CustomersDataTable = ds.Customers

        Dim rowCustomer As Chapter9.CustomersRow

        rowCustomer = tblCustomers.NewCustomersRow

        rowCustomer.CustomerID = "ABCDE"

        rowCustomer.CompanyName = "ABCDE有限公司"

        rowCustomer.ContactName = "ABCED联系人"

        rowCustomer.Phone = "(800) 555-1212"

        tblCustomers.AddCustomersRow(rowCustomer)

或者这样写:

Dim rowCustomer as DataRow=tblCustomers.NewRow()

rowCustomer(“CustomerID”)=”ABCED”

...

tblCustomers.Row.Add(rowCustomer)

 

强类型DataRow的优越性之一就是,在IDE中可以直接支持语句完成(Statement Completion)功能。

但是,尽管在VB5开始就已经支持语句完成,但是如果在VB6ADO2.x代码中输入错误的列名,那么要到运行时才会发现该错误,强类型DataSet和语句完成都无法消除开发时出现的此种问题。

强类型的Add《表名》Row,这个方法也有重载版本。

Dim ds as New Chapter9()

Dim tblCustomers As Chapter9.CustomersDataTable=ds.Customers

tblCustomers.AddCustomersRow(“ABCDE”,”NewCompany”,”NewCantact”,”555-1212”)

上句可替换为

tblCustomers.Rows.Add(new Object(){“ABCDE”,”New Company”,”New Contact”,”555-1212”})

IntelliSense和语句完成是在编写代码时,给人印象最深的特性之一。

2.2         查找行

对于标准非类型化DataSet,可以“根据主键值”,利用DataTable.Rows集合的Find方法,查找特定行。

但是,有时候Find方法会造成混淆,尤其是主键是组合键的情形,例如Northwind数据库中的Order Details表,其主键是OrderIDProductID

如果DataTable有一个定义过的主键,那么强类型的DataSet的每一个DataTable都公开自己的Find方法。给强类型DataSet中使用组合键作为主键的表编写查找代码很容易。

        daOrderDetails.Fill(Chapter91, "Order Details")

        DataGridView1.DataSource = Chapter91.Order_Details

        Dim tblDetails As Chapter9.Order_DetailsDataTable = Chapter91.Order_Details

        Dim rowDetails As Chapter9.Order_DetailsRow

        rowDetails = tblDetails.FindByOrderIDProductID(10248, 59)

        If rowDetails Is Nothing Then

            MsgBox("行没找到")

        Else

            MsgBox("找到行!" & vbCrLf & "其订单ID为:" & rowDetails.OrderID & " - " & "产品ID为:" & rowDetails.ProductID)

        End If

2.3         编辑行

对强类型DataSet中的行进行编辑的过程与编辑标准数据集中的行类似,

            可供选择的方法有BeginEditEndEditCancelEdit

            也可以使用强类型DataRow的属性来访问DataRow列的值。

2.4         处理空数据

可以使用DataRow对象的IsNull函数对空值进行检验;使用System.Convert.DBNull可以给列指派一个空值。

强类型数据集对空值处理是:

            每一个强类型的DataRow中,各列都可以:校验列是否包含空值(Is<列名>Null);设置列值为空(Set<列名>Null)

        '首先添加数据

        daCustomers.Fill(Chapter91, "Customers")

        Dim tblCustomers As Chapter9.CustomersDataTable = Chapter91.Customers

        DataGridView1.DataSource = tblCustomers

 

        Dim rowCustomer As Chapter9.CustomersRow

        rowCustomer = tblCustomers.FindByCustomerID("AROUT")

 

        If rowCustomer Is Nothing Then

            MsgBox("没找到")

            Exit Sub

        End If

 

        '检验公司名空值

        If rowCustomer.IsCompanyNameNull() Then

            MsgBox("第一次检验- 公司名为空值")

        Else

            MsgBox("第一次检验- 公司名为: " & rowCustomer.CompanyName)

        End If

        '设置空值

        rowCustomer.SetCompanyNameNull()

        '检验公司名空值

        If rowCustomer.IsCompanyNameNull() Then

            MsgBox("第次检验- 公司名为空值")

        Else

            MsgBox("第次检验- 公司名为: " & rowCustomer.CompanyName)

        End If

2.5         处理层次数据

DataRow对象中,公开的两种通过层次数据进行查找的方法是:GetChildRowsGetParentRow。这两种方法需要提供引用的DataRelation的名字或者其对象本身。

在强类型DataSet中,如果存在DataRelation,则不需要指定DataRelation或其名称,XML架构定义工具将自动添加该方法。

具体的说:在强类型数据集中,给Customers表和Orders表建立关联,将更改保存到xsd文件,xml架构定义工具就会为Customers表添加GetOrdersRows方法到强类型DataRow类中,并为Orders表将GetCustomersRows方法添加到强类型DataRow类中。

        Dim ds As Chapter9 = Chapter91

        daCustomers.Fill(ds)

        daOrders.Fill(ds)

 

        Dim rowCustomer As Chapter9.CustomersRow

        Dim rowOrder As Chapter9.OrdersRow

        For Each rowCustomer In ds.Customers

            ListBox1.Items.Add("客户" & rowCustomer.CompanyName & "的订单")

            For Each rowOrder In rowCustomer.GetOrdersRows()

                ListBox1.Items.Add(vbTab & "订单编号- " & rowOrder.OrderID & vbTab & "下定日期- " & rowOrder.OrderDate)

            Next

        Next

上面代码对应的非强类型数据集代码是

Dim rowCustomer,rowOrder As DataRow

For Each rowCustomer In ds.Tables(“Customers”).Rows

     Console.WriteLine(“Orders for “ & rowCustomer(“CompanyName”))

     For Each rowOrder In rowCustomer.GetChildRows(“CustomersOrders”)

            ...

...

2.6         其他的DataSetDataTableDataRow特性

XML架构定义工具生成的类是:DataSet的派生类、DataTable的派生类、DataRow的派生类

因此,可以将它们看做是其非类型化的相应类。

例如:强类型DataSet没有可读写XML数据和架构信息的方法,但是由于派生关系,仍然公开了ReadXMLWriteXml等方法。

对于像用DataAdapter获取数据或提交更改之类的任务,可将强类型DataSet等同于普通DataSet对待。

3          何时使用强类型DataSet

3.1         软件组件

简单的组件,通常比那些提供一大串功能的组件运行的快。

强类型的DataSet,明显比非类型化的DataSet公开的功能要强大。但是,如果不使用附加配件的话,构造简单的,会更好。

3.2         设计时的优势

强类型DataSet在设计时的优势:编写访问代码很容易(这要感谢IDE的语句完成和智能感知IntelliSense功能)。

因为,强类型DataSet的初始化代码中,包含了创建架构和必要的DataTableDataColumnDataRelation以及Constraint所需的代码。

使用非类型化DataSet,有三种“将架构信息添加到DataSet的方法”:

1.                  自己编写代码;

2.                  使用DataSet对象的ReadXmlSchema方法,从XSD文件中加载架构;

3.                  使用DataAdapter对象的FillSchema方法

如果正在建立一个使用数据绑定的Windowsweb应用程序,那么,使用强类型数据集可以,更容易的在设计时绑定组件。为什么?因为,强类型DataSet包含自己的架构信息,所以能够给一列绑定控件。

创建多层应用程序时,可以通过强类型DataSet,将一个引用添加到一个类库,或将其添加到一个返回强类型DataSetWeb服务是,项目会复制XSD文件和强类型DataSet的类文件,客户端应用程序就能利用强类型DataSet在设计时的优势。

3.3         运行时优势

强类型DataSet对象的运行时含义是什么?它们如何影响应用程序的性能?

使用强类型DataSet对象,不仅易于编写代码,而且,代码还能提高应用程序的性能。

强类型代码,运行速度几乎是非类型化代码的,两倍。

强类型DataSet是如何提高性能的?DataRow对象允许通过提供列的名称、列的序号或DataColumn对象本身来访问列的内容。使用真正DataColumn对象的代码性能最好;使用列的名称编写代码最容易,但是性能最差。

XML架构定义工具生成的代码兼顾了两方面的优点。编写的代码容易维护,并且自动生成的代码使用了DataColumn对象。

任何程序员无法编写的代码,对于强类型DataSet对象来说,也同样无法生成。

实际上,所有强类型DataSet能实现的功能,都可以编码实现。

比如:要想以访问强类型DataSet那样的性能,访问一个非类型化DataSet的内容,就要避免在集合中执行基于字符串的查找,而使用基于索引的查找,或维护非类型化DataSet中的列引用。

修改代码:在非类型化DataSet中使用适当的DataColumn对象访问行的内容,并使用适当的类型转换代码,结果是新改进的访问比访问强类型DataSet的代码快5%10%

由于创建、填充和访问强类型DataSet需要更多的时间,所以这里非类型化DataSet比强类型DataSet性能上稍微好一点。

3.4         其他注意事项

决定使用强类型DataSet,还需要考虑其他一些问题。

3.4.1   进行结构更改

如果,需要通过添加或修改DataColumn对象来更改强类型DataSet对象的结构,则,必须重新生成强类型DataSet对象,特别是在生成一个多层应用程序(并且中间层返回强类型DataSet)时。

如果重新生成了强类型DataSet(中间层要返回的),就需要在对中间层的引用进行刷新之后,重新生成客户端程序。

但是,如果准备改变服务器返回的数据结构时,不论是否使用强类型DataSet,都需要改变访问该结构的客户端代码。

3.4.2   转换DataSet对象

由于强类型DataSet继承自标准DataSet,因此,通过“一个非类型化DataSet接口访问强类型DataSet的代码”是正确的。

比如:

Dim dsStrong as New Chapter9()

Dim dsUntyped as DataSet

dsUntyped=Ctype(dsStrong,DataSet)

但是,还要特别注意这个问题:

Dim dsStrong1,dsStrong2 as Chapter9

Dim dsUntyped as DataSet

下面是能成功的代码

Strong1=new Chapter9()

dsUntyped=Ctype(dsStrong1,DataSet)

dsStrong2=Ctype(dsUntyped,Chapter9)

下面的代码则会抛出异常

dsUntyped=New DataSet()

dsStrong2=Ctype(dsUntyped,Chapter9)

如果,有一个非类型化的DataSet,想使用强类型DataSet访问它,该怎么办?

(这里说的是,原有DataSet是非典型的DataSet

可以使用强类型DataSetMerge方法,从非类型化DataSet中导入数据。

Dim dsStrong as New Chapter9()

Dim dsUntyped as New DataSet()

dsStrong.Merge(dsUntyped)

Merge方法,有助于在两个不同的“强类型DataSet”实例之间,转移数据。

如果对WriteXmlReadXml方法的调用,包含Xml架构的话,还可以使用WriteXmlReadXml方法在两个不同的强类型DataSet类实例之间转移数据。

3.4.3   强类型DataSet对象的非类型化特性

假如,应用程序使用强类型DataSet,并且想要将DataSet送回中间层服务器,然后将更改提交给数据库的话,可以使用强类型DataSet对象提供的GetChanges方法,来创建一个只包含被修改的行的新DataSet,并且,GetChanges方法返回非类型化DataSet

能否将GetChanges方法返回的非类型化DataSet,再转化成强类型DataSet呢?当然是可以的。

Dim dsStrongAllRows as New Chapter9()

对强类型进行填充,并修改一些行,此处代码省略

Dim dsUntyped as DataSet

dsUntyped=dsStrongAllRows.GetChanges()

Dim dsStrongModifiedRows as Chapter9

dsStrongModifiedRows=Ctype(dsUntyped,Chapter9)

强类型DataSet,还有其他返回非类型化数据的方法,比如,Select方法,返回DataRow对象的一个数组,不能将返回数组转化为强类型DataSet对象的数组,但是可以将单个DataRow对象转化为相应的强类型DataRow

相似的规则也可用于DataView,虽然不能直接通过强类型DataSet类访问它的内容,但是能够将通过DataRowViewRow属性返回的DataRow转化为强类型的。

Dim dsStrong as New Chapter9()

对此对象填充数据,和修改部分行,代码略

Dim vueCustomers as New DataView(dsStrong.Customers)

Dim rowCustomer as Chapter9.CustomersRow

rowCustomer=Ctype(vueCustomers(0).Row,Chapter9.CustomersRow)

3.5         方法的选择

什么样的选择才是正确的?

强类型DataSet,能够更快的创建应用程序,能够更容易的编写高效的代码。

但是它们不提供最好的性能。

如果结合非类型化DataSet和智能代码来使用,就可以创建运行更快的程序。

选择,完全取决于程序的需要。

如果程序的性能不是最优先的考虑事项,应该使用非类型化DataSet对象;但是如果牺牲一部分性能来换取开发时间是值得的,那么就应该考虑使用强类型DataSet

posted @ 2008-12-02 14:46  怒杀神  阅读(1195)  评论(0编辑  收藏  举报