第三篇   数据库编程

第一章     基本概念

ASP.NET中的ADO.NETASP中的ADO相对应,它是ADO的改进版本。在ADO.NET中,通过Managed Provider所提供的应用程序编程接口(API),可以轻松地访问各种数据源的数据,包括OLEDB所支持的和ODBC支持的数据库。

下面介绍ADO.NET中最重要的两个概念:Managed ProviderDataSet

3.1.1 Managed Provider

过去,通过ADO的数据存取采用了两层的基于连接的编程模型。随着多层应用的需求不但增加,程序员需要一个无连接的模型。ADO.NET就应运而生了。ADO.NETManaged Provider就是一个多层结构的无连接的一致的编程模型。

 

Managed Provider提供了DataSet和数据中心(如MS SQL)之间的联系。Managed Provider包含了存取数据中心(数据库)的一系列接口。主要有三个部件:

l          连接对象Connection、命令对象Command、参数对象Parameter提供了数据源和DataSet之间的接口。DataSetCommand接口定义了数据列和表映射,并最终取回一个DataSet

l          数据流提供了高性能的、前向的数据存取机制。通过IdataReader,你可以轻松而高效地访问数据流。

l          更底层的对象允许你连接到数据库,然后执行数据库系统一级的特定命令。

过去,数据处理主要依赖于两层结构,并且是基于连接的。连接断开,数据就不能再存取。现在,数据处理被延伸到三层以上的结构,相应地,程序员需要切换到无连接的应用模型。这样,DataSetCommand就在ADO.NET中扮演了极其重要的角色。它可以取回一个DataSet,并维护一个数据源和DataSet之间的“桥”,以便于数据访问和修改、保存。DataSetCommand自动将数据的各种操作变换到数据源相关的合适的SQL语句。从图上可以看出,四个Command对象:SelectCommandInsertCommandUpdateCommandDeleteCommand分别代替了数据库的查询、插入、更新、删除操作。

Managed Provider利用本地的OLEDB通过COM Interop来实现数据存取。OLEDB支持自动的和手动的事务处理。所以,Managed Provider也提供了事务处理的能力。

 

3.1.2 DataSet

DataSetADO.NET的中心概念。你可以把DataSet想象成内存中的数据库。正是由于DataSet,才使得程序员在编程序时可以屏蔽数据库之间的差异,从而获得一致的编程模型:


DataSet支持多表、表间关系、数据约束等等。这些和关系数据库的模型基本一致。

 

3.1.2.1  TablesCollection对象

DataSet里的表(Table)是用DataTable来表示的。DataSet可以包含许多DataTable,这些DataTable构成TablesCollection对象。

DataTable定义在System.Data中,它代表内存中的一张表(Table)。它包含一个称为ColumnsCollection的对象,代表数据表的各个列的定义。DataTable也包含一个RowsCollection对象,这个对象含有DataTable中的所有数据。

       DataTable保存有数据的状态。通过存取DataTable的当前状态,你可以知道数据是否被更新或者删除。

 

3.1.2.2  RelationsCollection对象

各个DataTable之间的关系通过DataRelation来表达,这些DataRelation形成一个集合,称为RelationsCollection,它是DataSet的子对象。DataRelation表达了数据表之间的主键-外键关系,当两个有这种关系的表之中的某一个表的记录指针移动时,另一个表的记录指针也随之移动。同时,一个有外键的表的记录更新时,如果不满足主键-外键约束,更新就会失败。

通过建立各个DataTable之间的DataRelation,可以轻松实现在ASP中需要通过DataShaping才能实现的功能。

 

3.1.2.3   ExtendedProperties对象

在这个对象里可以定义特定的信息,比如密码、更新时间等。

 

3.1.2.4 小结

本章首先介绍在asp.net中数据库编程的两个基本概念Managed ProviderDataSet。在asp.net中,DataSet屏蔽了具体数据源和应用之间差异,使得应用摆脱了具体数据的束缚。在我们今后的数据库编程中,可以把DataSet视为远端数据库在内存中的镜像,把繁琐的数据库操作任务交给Managed Provider去做。

第二章  通过ADO.NET访问数据库

3.2.1  ADO.NET访问数据库的步骤

不论从语法来看,还是从风格和设计目标来看,ADO.NET都和ADO有显著的不同。在ASP中通过ADO访问数据库,一般要通过以下四个步骤:

1、       创建一个到数据库的链路,即ADO.Connection

2、       查询一个数据集合,即执行SQL,产生一个Recordset

3、       对数据集合进行需要的操作;

4、       关闭数据链路。

ADO.NET里,这些步骤有很大的变化。ADO.NET的最重要概念之一是DataSetDataSet是不依赖于数据库的独立数据集合。所谓独立,就是:即使断开数据链路,或者关闭数据库,DataSet依然是可用的。如果你在ASP里面使用过非连接记录集合(Connectionless Recordset),那么DataSet就是这种技术的最彻底的替代品。

有了DataSet,那么,ADO.NET访问数据库的步骤就相应地改变了:

l             创建一个数据库链路;

l             请求一个记录集合;

l             把记录集合暂存到DataSet

 

l             如果需要,返回第2步;(DataSet可以容纳多个数据集合)

l             关闭数据库链路;

l             DataSet上作所需要的操作。

DataSet在内部是用XML来描述数据的。由于XML是一种平台无关、语言无关的数据描述语言,而且可以描述复杂数据关系的数据,比如父子关系的数据,所以DataSet实际上可以容纳具有复杂关系的数据,而且不再依赖于数据库链路。

3.2.2  ADO.NET对象模型概览

3.2.2.1 ADOConnection

ADO.NET有许多对象,我们先看看最基本的也最常用的几个。首先看看ADOConnection。和ADOADODB.Connection对象相对应,ADOConnection维护一个到数据库的链路。为了使用ADO.NET对象,我们需要引入两个NameSpaceSystem.DataSystem.Data.ADO,使用ASP.NETImport指令就可以了:

 

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.ADO" %>

 

ADOConnection对象类似,ADOConnection对象也有OpenClose两个方法。下面的这个例子展示了如何连接到本地的MS SQL Server上的Pubs数据库。

 

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.ADO" %>

<%

  '设置连接串...

  Dim strConnString as String

  strConnString = "Provider=SQLOLEDB; Data Source=(local); " & _

                  "Initial Catalog=pubs; User ID=sa"

 

  '创建对象ADOConnection

  Dim objConn as ADOConnection

  objConn = New ADOConnection

 

  '设置ADOCOnnection对象的连接串

  objConn.ConnectionString = strConnString

 

  objConn.Open()  '打开数据链路

 

  '数据库操作代码省略

 

  objConn.Close()    '关闭数据链路

  objConn = Nothing  '清除对象

%>

 

上面的代码和ADO没有什么太大的差别。应该提到的是,ADO.NET提供了两种数据库连接方式:ADO方式和SQL方式。这里我们是通过ADO方式连接到数据库。关于建立数据库连接的详细信息,我们在后面的篇幅中将会讲到。

3.2.2.2 ADODatasetCommand

另一个不得不提到的ADO.NET对象是ADODatasetCommand,这个对象专门负责创建我们前面提到的DataSet对象。另一个重要的ADO.NET对象是Dataview,它是DataSet的一个视图。还记得DataSet可以容纳各种各种关系的复杂数据吗?通过Dataview,我们可以把DataSet的数据限制到某个特定的范围。

下面的代码展示了如何利用ADODatasetCommandDataSet填充数据:

 

  '创建SQL字符串

  Dim strSQL as String = "SELECT * FROM authors"

 

  '创建对象ADODatasetCommand Dataset

  Dim objDSCommand as ADODatasetCommand

  Dim objDataset as Dataset = New Dataset

  objDSCommand = New ADODatasetCommand(strSQL, objConn)

 

  '填充数据到Dataset

  '并将数据集合命名为 "Author Information"

  objDSCommand.FillDataSet(objDataset, "Author Information")

3.2.3显示Dataset

前面我们已经把数据准备好。下面我们来看看如何显示Dataset中的数据。在ASP.NET中,显示DataSet的常用控件是DataGrid,它是ASP.NET中的一个HTML控件,可以很好地表现为一个表格,表格的外观可以任意控制,甚至可以分页显示。这里我们只需要简单地使用它:

 

<asp:DataGrid id="DataGridName" runat="server"/>

 

剩下的任务就是把Dataset绑定到这个DataGrid,绑定是ASP.NET的重要概念,我们将另文讲解。一般来说,你需要把一个Dataview绑定到DataGrid,而不是直接绑定Dataset。好在Dataset有一个缺省的Dataview,下面我们就把它和DataGrid绑定:

 

    MyFirstDataGrid.DataSource = _

          objDataset.Tables("Author Information").DefaultView

    MyFirstDataGrid.DataBind()

 

3.2.4完整的代码

(code\122301.aspx)

 

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.ADO" %>

<%

  '设置连接串...

  Dim strConnString as String

  strConnString = "Provider=SQLOLEDB; Data Source=(local); " & _

                  "Initial Catalog=pubs; User ID=sa"

 

  '创建对象ADOConnection

  Dim objConn as ADOConnection

  objConn = New ADOConnection

 

  '设置ADOCOnnection对象的连接串

  objConn.ConnectionString = strConnString

 

  objConn.Open()  '打开数据链路

 

  '创建SQL字符串

  Dim strSQL as String = "SELECT * FROM authors"

 

  '创建对象ADODatasetCommand Dataset

  Dim objDSCommand as ADODatasetCommand

  Dim objDataset as Dataset = New Dataset

  objDSCommand = New ADODatasetCommand(strSQL, objConn)

 

  '填充数据到Dataset

  '并将数据集合命名为 "Author Information"

  objDSCommand.FillDataSet(objDataset, "Author Information")

 

  objConn.Close()    '关闭数据链路

  objConn = Nothing  '清除对象

 

 

  Authors.DataSource = _

          objDataset.Tables("Author Information").DefaultView

  Authors.DataBind()

 

%>

 

<HTML>

<BODY>

<asp:DataGrid id="Authors" runat="server"/>

</BODY>

</HTML>

3.2.5运行效果

 

 


3.2.6 小结

本章详细介绍了如何使用ADO.NET方法访问数据库的步骤,并给出了一个具体的例子演示如何从服务器端取得pubs数据库中的authors表的数据到本地的DataSet中,然后使用DataGrid控件绑定到DataSet上,最后在客户端显示。虽然这还比较简单,但这却是最常用的技术。

第三章  ADO.NET数据连接方法

3.3.1数据库连接字符串

一个Web应用往往包括几十上百个ASPX文件。如果在每一个文件里都是直接构造这个数据库连接字符串,首先是觉得麻烦,其次,如果数据库发生了什么变化,比如密码变化,或者IP变化,难道你都要改动每一个ASPX文件?

在《轻松组建网上商店》第一版里,我们通过把数据库连接字符串封装到Application(“strConn”)变量里面,在global.asa中初始化这个Application变量,从而解决了这个难题。

另外的一个解决方法就是写一个DbOpen函数,放到独立的一个ASP文件里,然后在其他的文件里包含这个DbOpen函数所在的文件。

这些方法在ASP时代非常流行。在ASP.NET时代,这些方法大部分依然有效,但是这里介绍的方法,却是利用了ASP.NET的特性。我们如果学习ASP.NET,就一定要按照ASP.NET的风格来编写代码。这样会给你带来意想不到的性能提高。

和在ASP里面类似,ASP.NET也有一个Application一级的配置文件,叫做config.web。通过简单地配置config.web,就可以解决数据库连接字符串问题:

 

(config.web)

<configuration>

        <appsettings>

                <add key="strConn" value="server=localhost;uid=sa;pwd=;Database=pubs"/>

        </appsettings>

</configuration>

 

aspx页面里,我们可以这样获得数据库连接字符串:

Dim MyConnection As SQLConnection

Dim Config as HashTable

 

config.webappsettings全部读到临时对象中

Config = Context.GetConfig("appsettings")

‘Config临时对象实际上是一个集合。

MyConnection = New SQLConnection(Config("MyConn"))

 

关于config.web的详细介绍,请阅读后面的章节。

 

此处要说明的是,本书为了使各个例子相对独立,没有采用上面介绍的方法。

3.3.2两种数据库连接方式

ASP.NET不仅带来了ADO.NET,还带来了SQL Managed Provider。这样在ASP.NET里,我们就有了两种连接数据库的方式:

1、ADO.NET Managed Provider

2、SQL Managed Provider

其中,方式一可以连接到任何ODBC或者OLEDB数据中心,而方式二可以连接到MS SQL Server。仅仅就MS SQL Server来讲,使用方式二在性能上要优于方式一。

下面我们来看看数据库连接的各种情况。

3.3.2.1 ADO.NET Managed ProviderODBC

我们要连接的数据库是MS SQL Server中的pubs数据库。首先我们创建一个DSN:控制面板>>管理工具>>数据源(ODBC)>>添加:

下面的代码就创建了一个到MS SQL Serverpubs数据库的连接:

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.ADO" %>

 

<script language=”VB” RunAt=”Server”>

  '创建对象ADOConnection

  Dim objConn as ADOConnection=New ADOConnection(“DSN=pubs”)

  objConn.Open()  '打开数据链路

</script>

 

注意开始的两个Import语句。这是ADO.NET对象所在的Namespace

 

ADO.NET Managed Provider+ODBC可以连接到各种数据源,包括:MS SQL ServerAccessExcelmySQLOracle,甚至格式化的文本文件等等。

 

3.3.2.1.1一个完整的例子

<%@ Page Language="vb" %>

<%@ Import Namespace = "System.Data" %>

<%@ Import Namespace = "System.Data.ADO" %>

<html>

  <head>

  <script runat=server>

       Sub Page_Load(ByVal Sender As Object, ByVal e As EventArgs)

              On Error Resume Next

              Dim cn           As ADOConnection

 

              cn = New ADOConnection("DSN=NWind")

              cn.Open()

              If cn.State = 1 Then

                     lblReturnCode.Text = "The Connection State is: " & cn.State & " - Connection Succeeded"

              Else

                     lblReturnCode.Text = "The Connection State is: " & cn.State & " - Connection Failed"

              End If

       End Sub

       </script>

  </head>

  <body>

       <asp:Label id="lblReturnCode" Runat=server />

  </body>

</html>

 

3.3.2.2 ADO.NET Managed ProviderOLEDB

建立一个到OLEDB数据中心的连接,就需要精心构造数据库连接字符串。下面的代码建立了一个到Access数据库的连接:

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.ADO" %>

 

<script language=”VB” RunAt=”Server”>

Dim cn As ADOConnection cn = New ADOConnection("provider=Microsoft.Jet.OLEDB.4.0; " & _

  "Data Source=C:\Program Files\Microsoft Office\Office\Samples\Northwind.mdb;")

cn.Open()

</script>

 

下面的代码建立了到MS SQL Server数据库的连接:

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.ADO" %>

 

<script language=”VB” RunAt=”Server”>

Dim cn As ADOConnection cn = New ADOConnection("Provider=SQLOLEDB.1;Data Source=(local);uid=sa;pwd=;Initial Catalog=pubs”)

cn.Open()

</script>

 

ADO.NET目前支持下面的几个OLEDB

OLEDB驱动程序

提供者

SQLOLEDB

SQL OLE DB Provider

MSDAORA 

Oracle OLE DB Provider

JOLT

Jet OLE DB Provider

MSDASQL/SQLServer ODBC

SQL Server ODBC Driver via OLE DB for ODBC Provider

MSDASQL/Jet ODBC

Jet ODBC Driver via OLE DB Provider for ODBC Provider

 

(数据来源:http://msdn.microsoft.com/library/default.asp?URL=/library/dotnet/cpguide/cpconaccessingdatawithado.htm )

 

3.3.2.2.1一个完整的例子

<%@ Page Language="vb" %>

<%@ Import Namespace = "System.Data" %>

<%@ Import Namespace = "System.Data.ADO" %>

<html>

  <head>

  <script runat=server>

       Sub Page_Load(ByVal Sender As Object, ByVal e As EventArgs)

              On Error Resume Next

              Dim cn           As ADOConnection

 

              cn = New ADOConnection("provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Program Files\Microsoft Office\Office\Samples\Northwind.mdb;")

              cn.Open()

              If cn.State = 1 Then

                     lblReturnCode.Text = "The Connection State is: " & cn.State & " - Connection Succeeded"

              Else

                     lblReturnCode.Text = "The Connection State is: " & cn.State & " - Connection Failed"

              End If

       End Sub

       </script>

  </head>

  <body>

       <asp:Label id="lblReturnCode" Runat=server />

  </body>

</html>

 

3.3.2.3 SQL Managed ProviderMicrosoft SQL Server

通过SQL Managed Provider 建立到MS SQL Server的连接很简单:

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.SQL" %>

 

<script language=”VB” RunAt=”Server”>

  Dim objConn as SQLConnection = New ADOConnection("server=localhost;uid=sa;pwd=;database=pubs;")

 

  objConn.Open()  '打开数据链路

</script>

 

请注意几个地方:

1、   Import语句的不同。在ADO.NET Managed Provider里面,我们Import的是System.Data.ADO;而这里需要System.Data.SQL

2、   连接对象也不同。在ADO.NET Managed Provider中,所有的对象以ADO打头;而这里需要以SQL打头。

下面的表格归纳了这些不同:

 

ADO.NET Managed Provider

ADO.NET SQL Managed Provider

需要引入的Namespace

System.Data.ADO

System.Data.SQL

Connection对象

ADOConnection

SQLConnection

Command对象

ADODatasetCommand

SQLDatasetCommand

Dataset对象

Dataset

Dataset

DataReader

ADODataReader

SQLDataReader

连接数据库例子

String sConnectionString = "Provider= SQLOLEDB.1;

Data Source=localhost;

uid=sa; pwd=; Initial Catalog=pubs";

 

ADOConnection con = new ADOConnection(sConnectionString);

con.Open();

String sConnectionString = "server=localhost;uid=sa;pwd=;database=pubs";

SQLConnection con = new SQLConnection(sConnectionString);

con.Open();

 

执行SQL语句例子

ADOCommand cmd = new ADOCommand("SELECT * FROM Authors", con);

ADODataReader dr = new ADODataReader();

cmd.Execute(out dr);

SQLCommand cmd = new SQLCommand(("SELECT * FROM Authors", con);

SQLDataReader dr = new SQLDataReader();

cmd.Execute(out dr);

使用存储过程例子

ADOCommand cmd = new ADOCommand ("spGetAuthorByID", con);

cmd.CommandType = CommandType.StoredProcedure;

 

ADOParameter prmID = new ADOParameter("AuthID",

ADODataType.VarChar, 11);

 

prmID.Value = "111-11-1111";

 

cmd.SelectCommand.Parameters.Add(prmID);

 

ADODataReader dr;

cmd.Execute (out dr);

SQLCommand cmd = new SQLCommand("spGetAuthorByID", con);

cmd.CommandType = CommandType.StoredProcedure;

 

SQLParameter prmID = new SQLParameter("@AuthID",

SQLDataType.VarChar,11);

 

prmID.Value = "111-11-1111"

cmd.SelectCommand.Parameters.Add(prmID);

SQLDataReader dr;

cmd.Execute(out dr);

3.3.2.3.1一个完整的例子

<%@ Page Language="vb" %>

<%@ Import Namespace = "System.Data" %>

<%@ Import Namespace = "System.Data.SQL" %>

<html>

  <head>

  <script runat=server>

       Sub Page_Load(ByVal Sender As Object, ByVal e As EventArgs)

              'On Error Resume Next

              Dim cn           As SQLConnection

 

              cn = New SQLConnection("server=localhost;uid=sa;pwd=;database=pubs;")

              cn.Open()

              If cn.State = 1 Then

                     lblReturnCode.Text = "The Connection State is: " & cn.State & " - Connection Succeeded"

              Else

                     lblReturnCode.Text = "The Connection State is: " & cn.State & " - Connection Failed"

              End If

       End Sub

       </script>

  </head>

  <body>

       <asp:Label id="lblReturnCode" Runat=server />

  </body>

</html>

 

3.3.2.4 三种方法的对比

一般来说,这三种存取数据库的方法中,SQL Managed Provider效率最高,其次是ADO.NET Managed Provider+OLEDB,最差的是ADO.NET Managed Provider+ODBC。下面是在普通PIII微机上,对于Access 2000MS SQL Server 2000上的测试结果:

数据库连接类型

页面显示所需时间()

ADO.NET Managed Provider+ODBC

0.831195

ADO.NET Managed Provider+OLEDB

0.100144

SQL Managed Provider

0.060086

从图上可以看出,SQL Managed Provider要优于ADO.NET Managed Provider,而从ODBCOLEDB的对比来看,OLEDB要优于ODBC

下面列示了测试用的源程序,仅供参考。

3.3.2.5测试程序

(122303.aspx)

<%@ Page EnableSessionState="False" %>

 

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.ADO" %>

<%@ Import Namespace="System.Data.SQL" %>

 

 

<script language="VB" runat="server">

Sub Refresh(ByVal sender As System.Object, ByVal e As System.EventArgs)

       Dim d1,d2 As DateTime

      

       Dim strConn

       if Page.IsValid then

              d1=Now()

 

              Dim iChoice As Integer=CInt(Choices.SelectedItem.Value)

              select case iChoice

                     case 1

                            strConn="DSN=pubs;"

                            ADOBindData(strConn)

                     case 2

                            strConn="Provider=SQLOLEDB.1;Data Source=(local);uid=sa;pwd=;Initial Catalog=pubs"

                            ADOBindData(strConn)

                     case 3

                            strConn="server=localhost;uid=sa;pwd=;Database=pubs"

                            '"server=localhost;uid=sa;pwd=;database=northwind;"

                            SQLBindData(strConn)

                     Case Else

              end select

 

             

              d2=Now()

              result.Text = "用时(Ticks)"&d2.Ticks-d1.Ticks

       end if

End Sub

 

Sub ADOBindData(strConn)

  '设置连接串...

  '创建对象ADOConnection

  Dim objConn as ADOConnection = New ADOConnection(strConn)

 

  objConn.Open()  '打开数据链路

 

  '创建SQL字符串

  Dim strSQL as String = "SELECT * FROM authors"

 

  '创建对象ADODatasetCommand Dataset

  Dim objDSCommand as ADODatasetCommand

  Dim objDataset as Dataset = New Dataset

  objDSCommand = New ADODatasetCommand(strSQL, objConn)

 

  '填充数据到Dataset

  '并将数据集合命名为 "Author Information"

  objDSCommand.FillDataSet(objDataset, "Author Information")

 

  objConn.Close()    '关闭数据链路

  objConn = Nothing  '清除对象

 

 

  Authors.DataSource = _

          objDataset.Tables("Author Information").DefaultView

  Authors.DataBind()

End Sub

 

 

Sub SQLBindData(strConn)

  '设置连接串...

  '创建对象ADOConnection

  Dim objConn as SQLConnection = New SQLConnection(strConn)

 

  objConn.Open()  '打开数据链路

 

  '创建SQL字符串

  Dim strSQL as String = "SELECT * FROM authors"

 

  '创建对象SQLDatasetCommand Dataset

  Dim objDSCommand as SQLDatasetCommand

  Dim objDataset as Dataset = New Dataset

  objDSCommand = New SQLDatasetCommand(strSQL, objConn)

 

  '填充数据到Dataset

  '并将数据集合命名为 "Author Information"

  objDSCommand.FillDataSet(objDataset, "Author Information")

 

  objConn.Close()    '关闭数据链路

  objConn = Nothing  '清除对象

 

 

  Authors.DataSource = _

          objDataset.Tables("Author Information").DefaultView

  Authors.DataBind()

End Sub

 

</script>

 

<HTML>

<BODY>

<H2>测试设置</H2>

       <Form Action="122303.aspx" Method="Post" RunAt="Server">

       <asp:RadioButtonList ID="choices" RunAt="Server">

              <asp:ListItem selected Text="ADO.NET Managed Provider+ODBC" Value=1/><br>

              <asp:ListItem Text="ADO.NET Managed Provider+OLEDB"  Value=2/><br>

              <asp:ListItem Text="SQL Managed Provider" Value=3/>

       </asp:RadioButtonList>

       <br>

       <asp:LinkButton runat="server" OnClick="Refresh" Text="开始测试"/>

       <br>

<H2>测试结果</H2>

       <asp:label id="result" RunAt="Server" Text="No result"/>

       <br>

<H2>测试数据</H2>

       <asp:DataGrid id="Authors" runat="server"/>

       </Form>

</BODY>

</HTML>

 

 

3.3.3使用DataSets

       使用DataSets有两种方式,一是从数据库中得到,一是自己编程动态创建一个DataSets

使用从数据库端得到的DataSets方式主要是为了方便用户在客户端操作修改远端的数据库管理系统中的相应信息。而使用编程创建DataSets,是由于DataSets的数据事先并不知道,需要在程序运行中得到数据并填充进DataSets。采用DataSets作为本地数据来源中心的好处是,应用逻辑一样的程序就与数据来源不同分开,当数据源发生变化时,就只需要修改填充DataSets的程序而不用修改应用程序。

 

3.3.3.1从数据库得到DataSets的使用

       使用一个从数据库获得的DataSets较为复杂,它的步骤大概如下:

 

1.       使用SQLDataSetCommand命令(SQL方式)或者ADODataSetCommand命令(ADO方式)从数据库管理系统中获取一个表结构及其数据填充到本地内存的DataSet的一个表中。

 

例如:

·Ado方式

Dim MyDsComm As New ADODataSetCommand

Dim MyComm As ADOCommand

Dim MyConn As ADOConnection

 

MyConn = New ADOConnection _

("Provider=SQLOLEDB.1;Initial Catalog=Northwind;" & _

"Data Source=(local);User ID=sa;")

 

MyComm = New ADOCommand("SELECT * FROM Customers", MyConn)

MyDsComm.SelectCommand = MyComm

 

·SQL方式

Dim MyConn as SQLConnection

Dim MyComm as SQLDataSetCommand

Dim MyDs as New DataSet

 

MyConn=New SQLConnection(“server=localhost;uid=sa;pwd=;database=pubs”)

MyComm=New SQLDataSetCommand(“Select * from authoers”,MyConn)

MyComm.FillDataSet(Myds,”authers”)

 

 

2.对DataSet中的表对象DataTable的数据进行操作,包括增加、删除、修改它的DataRow对象

 

3.使用GetChanges方法产生一个DataSet修改后的对象的DataSet集合。

 

代码如下:

Dim changedDataSet As DataSet

changedDataSet = ds.GetChanges(DataRowState.Modified)

 

4.通过对产生的DataSet对象的HasErrors属性的监控,查看是否DataSet中的表有错误发生。

 

5.如果有错误发生,就要对DataSet中的各个表进行错误检查,方法一样,也是根据各个DataTableHasErrors属性。如果表中有错误发生,那么GetErrors方法就会被激活,并且会返回一个含有错误的DataRow对象的数组。

 

6.当表出错时,对于每一个DataRow对象的RowError属性进行检测。

 

7.如果可能,处理发生的错误。

 

8.使用DataSet对象的Merge方法把检测无错误发生的修改后的DataSet合并入原先的DataSet中,代码如下:

 

ds.Merge(changedDataSet)

 

9.使用DataSetCommand对象的update方法,把合并后的DataSet对象送往数据库端进行修改,代码如下:

 

               MyDataSetCommand.Update(ds)

 

10.使用DataSet对象的AcceptChanges方法对数据库修改进行确认,或者使用RejectChanges方法撤消对数据库的修改,代码如下:

 

        Ds.AcceptChanges

 

3.3.3.2编程实现DataSet

1.使用DataSet()创建器创立一个DataSet对象。

DataSet()可以跟一个字符串用以指明创建的DataSet名字

 

Dim ds1 as New DataSet

Dim ds2 as New DataSet(“MyDataSet”)

 

       2.增加一个DataTableDataSet中。

              具体操作是,首先在DataSet对象的Tables集合中,增加一个表

              ds.Tables.Add(New DataTable(表名))

              然后,再在该表中的Columns集合中增加相应的列

        ds.Tables(表名).Columns.Add(列名,列类型)

             

       例如:我们在ds对象中建立一个订购表(Order),它有三个字段,客户名(CUNM)、订货编号(ORNO)、订货数量(ORNM

 

              ds.Tables.Add(New DataTable(“Order”))

 

        ds.Tables(“Order”).Columns.Add(“CUNM”,GetType(String))

      ds.Tables(“Order”).Columns.Add(“ORNO”,GetType(String))

           ds.Tables(“Order”).Columns.Add(“ORNM”,GetType(int32))

 

           ds.Tables(“Order”).PrimaryKey=

                                       New DataColumn(ds.Tables(“Order”).Columns(“ORNO”)

    在上面的例子中,我们还设置了订购表的键值,这是通过对它的PrimaryKey的属性设置来得到的,设置键值的好处在于可以防止相同记录的输入,保证数据的唯一性。

 

3.设置表间的关系

    由于DataSet对象中可以含有多个DataTable,而事实上每一个表又不可能与其他的表没有任何的关系,这样就带来了一个问题,我们如何描述两个不同的表之间的关系?asp.net提供了DataRelation对象来描述表和表之间的关系。DataRelation对象至少需要两个参数才能确定两个表之间的关系,这是因为在两个表的关系中,至少需要一个主键列和一个外键列,才能确定两者之间的对应关系。

    例如:关于客户购物有两个表,一个是客户信息表(Customer),一个是购物信息表(Order),很显然它们两者之间存在着某种联系。经过分析,我们发现客户编号(CUNO)在两个表中都存在,它使我们能够把两个表的信息连接起来,告诉我们这样一个事实,谁订购了什么物品。因此需要建立关于客户信息表和购物信息表的一个联系,用Asp.net语言表达如下:

    Dim ds as DataSet

  …

  ds.Relations.Add(“CustomerOrder”,ds.Tables(“Customer”).Columns(“CUNO”),

                                                                   ds.Tables(“Order”).Columns(“CUNO”))

 

4.在关系表间的浏览

 

    通过DataRelaiton的设置,我们可以在同一个DataSet中,由对一个表操作,找到可能引起的相关表的变化。例如,对于客户信息表中的对应于某个人的一条记录,我们可以在购货信息表中找到所有属于他的购货信息,演示代码如下:

dim orderRows() as DataRow

   orderRows=ds.Tables(“Customer”).ChildRelations(“CustomerOrder”).GetChildRows(

                                                                   ds.Tables(“Customer”).Rows(0))

 

5.数据约束的使用

    在关系数据库中,使用数据约束的目的是为了使数据库的一致性得到保证。当数据发生改变时,数据约束被执行,用以检查对数据的修改,是否和已经定义的规则相符合,如果不符合修改将不能生效。在asp.net中提供了两种数据约束,ForeignKeyConstraintUniqueConstraint

 

    ForeignKeyConstraint,外键值一致性约束,定义当表中的一条记录被删除或者是增加一条记录时,与该表相关的其他表的相应记录如何处理。例如,当一个客户被人从客户信息表中删去,那么在购物信息表中的关于他的购物信息的记录如何处理等等。

    ForeignKeyConstraint有五个可能的值如下:

    ·Cascade     当表中记录被删除或者更新以后,对应表中的记录相应被删除和更新

    ·SetNull       当表中记录被删除或者更新以后,对应表中的记录被置为Null

    ·SetDefault 当表中记录被删除或者更新以后,对应表中的记录被置为缺省值

    ·None        当表中记录被删除或者更新以后,对应表中的记录不做任何处理

    ·Default       当表中记录被删除或者更新以后,ForeignKeyConstraint采用其缺省值,通常该值为Cascade

    具体使用ForeigKeyConstraint时,首先应创建它,然后设置DeleteRuleUpDateRule属性,指明当删除和更新记录时,对应表的处理规则。

   

    例子:我们对客户信息表定义一个外键定义,它定义当客户信息表中记录删除时,其关联表购物信息表中的数据也应删除(意味着用户不存在,自然也不应该有他的购物信息),当客户信息表中记录被修改时,购物信息置为缺省的特殊值(意味着,当销售人员发生差错,记错购物用户,那么以他的名义购物的定单不应算在该用户头上,置为特殊标记,以供今后修改),代码演示如下:

 

dim fk as New ForeignKeyConstraint(ds.Tables(“Customer”).Columns(“CUNO”),

                                                                   ds.Tables(“Order”.Columns(“CUNO”))

创建外键约束为Customer表和Order表中CUNO字段

fk.DeleteRule=Cascade

fk.UpdateRule=SetDefault

删除规则为Cascade,修改规则为SetDefault

ds.Tables(“Customer”).Constraints.Add(fk)

加入Customer表的一致性约束集合中

 

    UniqueConstraint,唯一性约束,它指定了数据表中的一个列或者几个列的集合的值的唯一性,通常被指定为唯一约束的字段都是表的键值。

    例如:对于客户信息表,因为每个人的购物都必须和别人区别,这样才能保证正确地付款和发送货物,因而每一个人的客户编号都不应该相同,这时就可以使用唯一性约束来保证客户信息表中的客户编号唯一。演示代码如下:

   

dim uc as UniqueConstraint

uc=New UniqueConstraint(ds.Tables(“Customer”).Columns(“CUNO”))

指定唯一约束为Customer表中的CUNO字段

ds.Tables(“Customer”).Constraints.Add(uc)

把唯一约束加入Customer表的约束中

 

6.处理DataSet的事件

    为了便于用户对DataSet的控制,asp.net提供了DataSet的一系列可被用户处理的事件,它们包括:

           ·PropertyChange   当属性发生改变时

           ·MergeFailed         DataSet合并失败时

           ·RemoveTable     删除一个表时

           ·RemoveRelation   删除一个关系时

           ·Adding the event handler to the event 增加一个事件处理函数时

 

例如:

ds.AddOnPropertyChange(new System.ComponentModel.PropertyChangeEventHandler _

(AddressOf me.DataSetPropertyChange))

指定当DataSet发生PropertyChange事件时的消息处理函数为DataSetPropertyChange

ds.AddOnMergeFailed(new System.Data.MergeFailedEventHandler _

(AddressOf me.DataSetMergeFailed))

指定当DataSet发生MergeFailed事件时的消息处理函数为DataSetMergeFailed

 

PropertyChange发生时的处理函数

Private Sub DataSetPropertyChange _

   (ByVal sender As Object, ByVal e As System.PropertyChangeEventArgs)

   …

End Sub

 

MergeFailed发生时的处理函数

Private Sub DataSetMergeFailed _

   (ByVal sender As Object, ByVal e As System.Data.MergeFaileedEventArgs)

  …

End Sub

 

3.3.3.3使用DataTable

       DataTableDataSet中一个对象,它与数据库表的概念基本一致,简单起见,你就可以把它认成是数据库DataSet中的表。

 

1.  创建一个DataTable

DataTable创建器跟使用DataSets创建器差不多,可以跟一个参数,用以指定表名。

 

例如:

       dim MyTable as DataTable

 

MyTable = New DataTable("Test")

MyTable.CaseSensitive = False

MyTable.MinimumCapacity = 100

 

其中CaseSensitive属性指定是否区分大小写,这里指定不区分,CaseSensitive属性是否打开对于查找、排序、过滤等操作有很大的影响。MinimumCapacity属性指定创建时保留给数据表的最小记录空间。另外还有一个TableName的属性,它指定数据表的名称,例如下面两种方式创建的表是一样的。

1)  dim MyTable as DataTable