ADO.NET

来源:互联网 发布:船舶数据 编辑:程序博客网 时间:2024/06/08 07:39
ADO.NET数据库编程比较复杂,名目繁多的类、对象、属性、方法让每一个编程者都感觉恼火。本文旨在介绍ASP.NET Beta2数据库编程的主要内容,帮助编程者最快的了解ADO.NET数据库编程的精髓。

 

  一、 Managed Providers

 

  如果你是初学者,可能你会问,什么是"Managed Providers"?

 

  Managed Providers提供简单的方法连接和访问数据库,有点类似于数据库连接,当然又比它强的多。Managed Providers提供OleDb和SQL Server两种编程接口。因为SQL Server是微软自己的产品,因此,专门提供了一个针对SQL Server的接口,使用这个接口访问SQL Server的效率应该比使用OleDb强。

 

  NameSpaces

 

  本文所有的例子程序都需要使用以下NameSpaces:

 

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

 

  Connection

 

  为了连接数据库,必须使用OleDbConnection:

 

Dim objConn as New OleDBConnection
("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=e:/sff/site/db/users.mdb")

 

  当然,你也可以将具体的连接方法作为变量使用,在连接数据库以后,必须打开数据库:

 

objConn.Open()

 

  这样,就可以使用数据库了,一般在最后,我们都要求关闭数据库连接:

 

objConn.Close()
objConn=Nothing

 

  Command

 

  连接数据库以后,就可以发送命令对数据库进行操作了,OleDbCommand允许发送命令对数据库进行操作。根据发送的SQL语句,我们可以对数据库进行几乎所有操作。

 

Dim objCmd as New OleDbCommand("SELECT * From users", objConn)

 

  以上语句建立Command,根据习惯不同,也可以使用以下方法:

 

Dim objCmd as New OleDbCommand()
objCmd.Connection = objConn
objCmd.CommandText = "SELECT * FROM users" 

 

  还可以这样:

 

Dim objCmd as New OleDbCommand(SQL String, connection string)

 

  仔细观察上面的语句,我们发现在定义OleDbCommand时,可以同时使用数据库连接OleDbConnection和数据库连接语句。以上代码并没有执行SQL语句,现在我们来看到底怎样执行:

 

  ExecuteNonQuery

 

  当执行没有返回数据的操作的时候,我们可以使用以上方法,比如插入数据、更新数据等操作,具体这样执行:

 

objCmd.ExecuteNoQuery

 

  ExecuteReader

 

  在需要一个Data Reader的时候,我们可以使用以上方法,具体这样执行:

 

Dim objRd as OleDbDataReader
objRd = objCmd.ExeuteReader

 

  ExecuteScalar

 

  使用ExecuteScalar方法来取得一个单个地返回数据,比如对数据的统计。

 

  Data Reader

 

  OleDbReader是专门用来读取数据的对象,这个对象除了读数据以外,不能做其他任何数据库操作。尽管比较简单,但是在用来浏览数据的时候效率是非常高的。

 

Dim objReader as OleDbDataReader
objReader = objCmd.ExecuteReader
While objReader.Read
Response.Write(objReader.GetString(0) & "<br>")
End While

 

  以上语句读取Command的返回结果的第一个字段,这个字段是字符型数据。我们可以使用其他方法取得各种类型的数据:

 

    GetBoolean(x)

 

    GetByte(x)

 

    GetBytes(x)

 

    GetChar(x)

 

    GetChars(x)

 

    GetDataTypeName(x) -取得数据类型

 

    GetDateTime(x)

 

    GetDecimal(x)

 

    GetDefaultStream(x)

 

    GetDouble(x)

 

    GetFieldType(x)

 

    GetFloat(x)

 

    GetGuid(x)

 

    GetInt16(x)

 

    GetInt32(x)

 

    GetInt64(x)

 

    GetName(x) - 取得字段名

 

    GetOrdinal(name) -根据字段名取得字段序号

 

    GetString(x)

 

    GetTimeSpan(x)

 

    GetValue(x)

 

    GetValues(values())

 

  以上方法都是Command返回数据。

 

  Data Adapter

 

  OleDbDataAdapter取得数据并且数据与DataSet之间建一座桥梁,可以这样使用:

 

Dim objAdapter as New OleDbDataAdapter("SELECT * FROM users", objConn)

 

  实现方法有点类似于OleDbCommand。OleDbAdapter可以填充DataSet,也可以修改数据然后提交以实现对具体数据的修改:

 

Dim ds as Dataset = New DataSet()
objAdapter.Fill(ds, "users")

 

  以上语句实现将SQL语句取得的Users表的数据填充到DataSet。

 

  Mappings

 

  Mappings可以实现对DataSet的列取别名:

 

objAdapter.TableMappings.Add("adbtable", "users")
With objAdapter.TableMappings(0).ColumnMappings
.Add("PID", "ID")
.Add("LastName", "LName")
.Add("StreetAddress", "Addy")
End With
objAdapter.Fill(ds)

 

  当使用了以上代码以后,就可以用ds.Tables("users")来代替ds.Tables("adbtable")了。

 

  Command Builder

 

  在下一章我们可以看到Command Builder的具体使用和强大功能。

 

  练习:

 

  如果你能理解以下代码,你就可以看下一章的内容了:

 

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<script language="VB" runat="server">
Sub Page_Load(sender as object, e as eventargs)

 

Dim objConn as New OleDBConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=e:/sff/site/db/users.mdb")
objConn.Open()

 

Dim ds as Dataset = New DataSet()
Dim objAdapter as New OleDbDataAdapter("SELECT * FROM users", objConn)
Dim objCmdBld As New OleDbCommandBuilder(objAdapter)

 

objAdapter.Fill(ds, "users")

 

End Sub
</script>

 

  二、 Data Set

 

  本章将介绍DataSet对象,DataSet对象包含内容很多,我们基本上都将涉及,包括DataTables、DataRows等。

 

  什么是DataSet

 

  回头看看ASP,我们知道当查询数据的时候,返回的数据是放在RecordSet中的,RecordSet只能保存返回的一个表的数据,而且它很不灵活。

 

  DataSet在RecordSet上增加了很多功能,并且,它可以保存多个返回的数据表结果。

 

  DataSet被分解为很多部分比如DataTables和DataRows,可以使用它们创建一个DataSet而不一定要连接到一个具体的数据库。当然,DataSet本身就是离线数据,所有的数据都可以离线使用而不必一直连接到数据库,只有需要对数据库进行编辑的时候才需要连接到数据库。

 

  实践

 

Dim ds1 As New DataSet()
Dim dtable As new DataTable("people")
With dtable.Columns
.Add("FName", System.Type.GetType("System.String"))
.Add("LName", System.Type.GetType("System.String"))
.Add("UID", System.Type.GetType("System.Int32"))
End With
dtable.Columns("UID").AutoIncrement = True
ds1.Tables.Add(dtable)

 

dim pkey() as DataColumn = {ds1.Tables("people").Columns("UID")}
ds1.Tables("people").PrimaryKey = pkey

 

  以上语句稍微有点复杂,我们来看看:

 

  前半部分我们建立了一个DataSet和一个叫People的DataTable,然后,我们为这个DataTable加入了三个列并将"UID"列设为自动递增。最后,将这个DataTable加入到了DataSet。

 

  第二部分我们现在不需要理解,只要知道定义了主键就可以了。

 

  DataTables

 

  DataTable就是一个数据表,我们可以对这个表进行如:增加数据、修改数据等操作。我们也可以通过DataSet建立一个DataTable:

 

Dim dtable As DataTable = ds1.Tables("people")

 

  这样,将DataSet的表People的结构和数据拷贝到了DataTable中,尽管它是无连接的,但是仍然可以通过修改这个DataSet来更新DataSet表,因此,如果我们在dtable中增加一列并且接受改变就以实现对DataSet的修改:

 

Dim row as DataRow = dtable.NewRow()
row(0) = "Philip"
row(1) = "Quinn"
dtable.Rows.Add(row)
dtable.AcceptChanges

 

  这样我们就建立了一个新的DataRow,这和用dtable.NewRow()建立一个新的数据列一样,我们还可以给这个列取名了Fname。

 

  因为以上的DataTable来自DataSet,如果我们使用dtable.AcceptChanges方法更新DataTable,DataSet也会被更新:

 

<%@ Import Namespace="System.Data" %>
<script language="VB" runat="server">
Sub Page_Load(sender as object, e as eventargs)
Dim ds1 As New DataSet()
Dim dtable As new DataTable("people")
With dtable.Columns
.Add("FName", System.Type.GetType("System.String"))
.Add("LName", System.Type.GetType("System.String"))
.Add("UID", System.Type.GetType("System.Int32"))
End With

 

dtable.Columns("UID").AutoIncrement = True
ds1.Tables.Add(dtable)

 

Dim dtable2 As DataTable = ds1.Tables("people")

 

Dim row as DataRow = dtable2.NewRow()
row(0) = "Philip"
row(1) = "Quinn"
dtable2.Rows.Add(row)
dtable2.AcceptChanges

 

Response.Write(ds1.Tables("people").Rows(0)("FName").ToString)
End Sub
</script>

 

  以上代码将显示"Philip",现在我们来看看具体过程:

 

  1、 建立一个DataSet和一个叫"People"的DataTable;

 

  2、 增加三个数据列并且设置它们的数据属性;

 

  3、 将它们加入到DataSet;

 

  4、 建立另外一个DataTable,这个DataTable是刚才建立的那个的拷贝;

 

  5、 用DataTable建立新的DataRow并加入数据;

 

  6、 接受数据改变同时更新了DataSet;

 

  7、 显示第一个数据列;

 

  DataRows

 

  DataRow是DataTable的数据列,刚才我们已经看到,我们可以使用DataTable的以下方法建立一个新的DataRow:

 

ds1.Tables("people").Rows(0)("FName") = "Phil"

 

  以上语句中,ds1.Tables("people")选择表"people",.Rows(0)选择表的第一行,("FName")选择表的字段为"Fname"。

 

  DataRows是数据列的集合,通过以下语句取得:

 

Dim drow as DataRowCollection = ds1.Tables("people").Rows

 

  对于DataRows,我们基本上不能做太多。如果针对一个具体的数据列,我们可以这样:

 

Dim drow2 as DataRow = drow.Item(0)

 

  需要修改这个列的数据,可以这样:

 

drow2(0) = "Philip"
drow2.AcceptChanges

 

  可能说了那么多,我们都觉得比较复杂,我们来看看这个图示:

 

 

 

  通过这个图示我们很容易就理清了DataSet、DataTable、DataRowCollection、DataRows、DataColumn和DataColumnCollection之间的相互关系。

 


  三、 DataSet的使用

 

  在第一章我们介绍了数据连接、执行查询等内容,第二章我们介绍了DataSet的方方面面,这一章我们将具体使用DataSet。

 

DataSet <-> Data Source

 

  DataSet和Data Source通过DataAdapter进行联系,当DataSet取得数据库数据以后,就和数据库断开连接,针对数据作的所有数据修改在没有提交以前都在DataSet里面保存。

 

  数据修改

 

  我们将通过一个小的举例来说明数据怎样被修改和提交。

 

  这是数据结构(Access设计)

 

 

Field Name

Type

FName

LName

ID

FName

Text

Philip

Quinn

1

LName

Text

Joesph

Payne

2

ID

AutoNumber

Douglas

Adams

3

 

 

Michael

Okuda

4

 

 

   举例一:

 

  我们将一段一段的看程序代码:

 

<%@ Page Language="VB" %>

 

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<script language="VB" runat="server">
Sub Page_Load(sender as object, e as eventargs)

 

  以上代码导入NameSpace同时说明编程语言为VB;

 

Dim objConn as New OleDBConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=e:/sff/site/db/test.mdb")
objConn.Open()

 

Dim ds as Dataset = New DataSet()
Dim objAdapter as New OleDbDataAdapter("SELECT * FROM users", objConn)
Dim objCmdBld as New OleDbCommandBuilder(objAdapter)

 

objAdapter.Fill(ds, "users")

 

  以上代码建立了Connection、DataAdapter和CommandBuilder,并且填充了DataSet。我们必须注意以下几点:

 

  一、 DataAdapter是数据和DataSet之间的桥梁;

 

  二、 CommandBuilder建SQL语句来执行;

 

Dim drow as DataRow

 

  以上语句声明一个DataRow;

 

drow = ds.Tables("users").NewRow()

 

drow(0) = "Gene"
drow(1) = "Rodenberry"
ds.Tables("users").Rows.Add(drow)

 

drow = ds.Tables("users").NewRow()

 

drow(0) = "Maxwell"
drow(1) = "Stewart"
ds.Tables("users").Rows.Add(drow)

 

  以上代码为DataSet增加一个新的列;

 

objAdapter.Update(ds, "users")

 

  以上代码将更新提交到数据库;

 

End Sub
</script>

 

  现在看看数据库,会发现已经多了两列。

 

  另外一个举例

 

  我们可以看一个完整的举例:

 

<%@ Page Language="VB" Debug="true" %>

 

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<script language="VB" runat="server">
Sub Page_Load(sender as object, e as eventargs)

 

Dim objConn as New OleDBConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=e:/sff/site/db/test.mdb")
objConn.Open()

 

Dim ds as Dataset = New DataSet()
Dim objAdapter as New OleDbDataAdapter("SELECT * FROM users", objConn)
Dim objCmdBld as New OleDbCommandBuilder(objAdapter)

 

objAdapter.Fill(ds, "users")

 

Dim drow as DataRow

 

drow = ds.Tables("users").Rows(1)

 

drow(0) = "Joseph"

 

ds.Tables("users").Rows(0).AcceptChanges

 

objAdapter.Update(ds, "users")

 

End Sub
</script>

 

  总结:

 

  以上我们知道了怎样更新DataSet的数据,可能那些并不是特别实用,下一章我们将涉及到用较好的方式显示数据和通过TextBox修改数据。

 

  四、数据显示和修改

 

  这一章我们将学习怎样显示数据,喜欢偷懒的你可以从拷贝以下代码开始:

 

<%@ Page Language="VB" Debug="true" %>

 

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<script language="VB" runat="server">
Sub Page_Load(sender as object, e as eventargs)

 

Dim objConn as New OleDBConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=e:/sff/site/db/test.mdb")
objConn.Open()

 

Dim ds as Dataset = New DataSet()
Dim objAdapter as New OleDbDataAdapter("SELECT * FROM users", objConn)
Dim objCmdBld as New OleDbCommandBuilder(objAdapter)

 

objAdapter.Fill(ds, "users")

 

  Repeater

 

  Repeater是一个根据面板循环显示数据的控件。

 

  ItemTemplate:数据主要在这里显示

 

  AlternativeItemTemplate:利用它可以应用交替的样式;

 

  HeaderTemplate:头格式;

 

  SeparatorTemplate:分隔数据列;

 

  FooterTemplate:脚格式

 

  DataBind()

 

  DataBind()将数据与页面控件绑定:

 

Repeater1.DataSource = ds.Tables("users").DefaultView
DataBind()

 

  以上代码将数据绑定到Repeater,如果没有绑定,数据不会显示。

 

  其他代码

 

  以下是举例的其他代码:

 

Rpt.DataSource = ds.Tables("users").DefaultView
DataBind()
End Sub
</script>
<html><body><font face="Arial" size="2">
<asp:repeater id="Rpt" runat="server">

 

<HeaderTemplate>
<table border="0" cellspacing="1" cellpadding="3">
<tr>
<td bgcolor="#6699FF" width="25%">Last Name</td>
<td bgcolor="#6699FF" width="25%">First Name</td>
</tr>
</HeaderTemplate>

 

<ItemTemplate>
<tr>
<td>
<%# Container.DataItem("LName") %>
</td><td>
<%# Container.DataItem("FName") %>
</td>
</tr>
</ItemTemplate>

 

<FooterTemplate>
</table>
</FooterTemplate>

 

</asp:repeater>
</font></body></html>

 

  说明:

 

  一、 设置了Repeater的DataSource;

 

  二、 绑定数据到Repeater;

 

  三、 Repeater数据控件开始;

 

  四、 HeadTemplate定义Repeater的头信息;

 

  五、 ItemTemplate定义具体数据填充;

 

  六、 FooterTemplate定义Repeater脚信息;
  DataList

 

  DataList和Repeater有点相似,和Repeater不同的是,DataList可以编辑数据。可以和Repeater一样使用Template,但是它具有两点不同:

 

   SelectedItemTemplate:显示选择的列;

 

   EditItemTemplate:显示要编辑的列;

 

  以下是一个使用DataList的简单举例:

 

dl.DataSource = ds.Tables("users").DefaultView
Databind()
End Sub
Sub dl_ItemCommand(sender as object, e as DataListCommandEventArgs)
dl.SelectedIndex = e.Item.ItemIndex
dl.DataBind()
End Sub
</script>

 

<html><body><font face="arial" size="2"><form runat="server">
<asp:datalist id="dl" runat="server"
HeaderStyle-BackColor="#6699FF"
SelectedItemStyle-BackColor="#6666FF"
SelectedItemStyle-ForeColor="#FFFFFF"
RepeatLayout = "table"
RepeatDirection = "vertical"
DataKeyField = "ID"
OnItemCommand="dl_ItemCommand">

 

<HeaderTemplate>
Last Name, click for full name.
</HeaderTemplate>

 

<ItemTemplate>
<asp:linkbutton id="b1" runat="server" Text='<%# Container.DataItem("LName") %>' CommandName = "select" />
<br>
</ItemTemplate>

 

<SelecteditemTemplate>
<%# Container.DataItem("LName") & ", " & Container.DataItem("FName") %>
<br>
</SelectedItemTemplate>
</asp:datalist>
</form></font>
</body>
</html>

 

  说明:

 

  一、 绑定数据以后,建立了一个过程;

 

  二、 将DataList放入Form中,因为在以下的步骤中要求根据选择列刷新页面;

 

  三、 接着定义了一些数据显示格式;

 

  四、 HeaderTemplate:DataList头信息;

 

  五、 ItemTemplate:加入链接,定义事件;

 

  六、 SelectedItemTemplate:显示First 和 Last Name;

 

  DataGrid

 

  可能它是功能最强大的控件,不管简单还是复杂它都可以实现。

 

  和ItemTemplate不同,DataGrid有不同类型的列:

 

   Bound Columns:DataGird默认列显示方式;

 

   Button Columns:按钮列;

 

   Edit Command Column:可以编辑的列;

 

   Hyperlink Column :带连接的列;

 

   Templated Column :自定义列显示;

 

dg.DataSource = ds.tables("users").DefaultView
DataBind()
End Sub
</script>

 

<asp:DataGrid id="dg" runat="server" />
以上代码很简单,就是绑定数据。
dg.DataSource = ds.tables("users").DefaultView
DataBind()
End Sub
</script>

 

<asp:DataGrid id="dg" runat="server"
BorderColor="black"
GridLines="vertical"
cellpadding="3"
cellspacing="1"
width="50%"
Font-Names="Arial"
Font-Size="10pt"
HeaderStyle-BackColor="#6699FF"
AlternatingItemStyle-BackColor="#6666FF"
AutoGenerateColumns="False">
<Columns>

 

<asp:BoundColumn HeaderText="ID" DataField="ID" />

 

<asp:templateColumn HeaderText="Name">
<ItemTemplate>
<asp:label id="Name" runat="server" Text='<%# Container.DataItem("FName") & " " & Container.DataItem("LName") %>' />
</ItemTemplate>
</asp:templatecolumn>

 

</Columns>

 

</asp:datagrid>

 


  可能有一点复杂,我们看说明:

 

  一、 绑定数据以后,设置了一些DataSet显示效果,包括字体、表宽、头信息背景颜色、交替背景颜色、是否自动生成数据表等;

 

  二、 加入一个自定义格式列,该列名为Name,由字段Fname和Lname组成;

 

  现在才刚刚开始

 

  可能现在你还没有感受到DataSet的好处,以后的章节我们将学习怎样编辑数据。

 

  五、理解DataGrid

 

  数据放入DataGrid以后,除了一般的显示以外,我们还需要对这些数据进行编辑、修改。看了前几个章节你可能认为DataGrid比较简单,数据处理也比较方便。其实,如果需要真正做一个应用,我们会发现前面的知识还远远不够。以下所用的数据库和前面的章节完全相同,一些设置我们可以参考前面章节。我们先来看代码:

 

<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.Oledb" %>
<script language="VB" runat="server">
Dim objConn as New OleDBConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=e:/sff/site/db/test.mdb")
Dim ds as Dataset = New DataSet()
Dim objAdapter as New OleDbDataAdapter("SELECT * FROM users", objConn)

 

Sub Page_Load(sender as object, e as eventargs)
objConn.Open()
objAdapter.Fill(ds, "users")
dg.DataSource = ds
dg.DataMember = "users"
If Not Page.IsPostBack Then
dg.Databind()
End If
End Sub

 

sub dg_edit(sender as object, e as DataGridCommandEventArgs)
dg.edititemindex = -1
dg.DataBind()
end sub

 

sub dg_cancel(sender as object, e as DataGridCommandEventArgs)
dg.edititemindex = -1
dg.databind()
end sub
</script>

 

  以上程序代码很简单直接,我们应该都可以看懂。只是需要注意Page_Load的对数据绑定的处理,在几乎所有的数据库程序中,我们都使用这种方式处理数据绑定,所以,这个处理方式一定要牢记。以上是数据连接和事件处理部分,现在我们看DataGrid部分。

 

  自定义DataGrid

 

  以下代码演示了自定义DataGrid的实现,在实际应用中,我们基本都是这样使用DataGrid,以下代码很有典型性,可以作为一个好的参考。

 

<form runat="server">
<asp:DataGrid id="dg" runat="server"
Bordercolor="black"
gridlines="vertical"
font-names="Arial"
font-size="10pt"
HeaderStyle-BackColor="#FFCC00" '表格头信息
ItemStyle-BackColor="#FFCC66" '每行背景色
AlternatingItemStyle-BackColor="#FFFFFF" '交替背景色
AutoGenerateColumns="False" '自定义每行
OnEditCommand="dg_edit" '以下三个事件处理
OnCancelCommand="dg_cancel"
OnUpdateCommand="dg_update">

 

'自定义每行显示
<Columns>
<asp:boundcolumn readonly="true" headertext="ID" DataField="Auto" />
<asp:boundcolumn headertext="First Name" DataField="Number1" />
<asp:boundcolumn headertext="Last Name" Datafield="Number2" />
<asp:editcommandcolumn edittext="Edit" CancelText="Cancel" UpdateText="Save" HeaderText="" />
</Columns>

 

</asp:dataGrid>
</form>

 

  以上代码中,自定义了数据编辑列,这些相应的处理在前面已经给出代码。我们现在来看事件处理。

 

  OnEditCommand

 

  以下是编辑按钮处理代码:

 

sub dg_edit(sender as object, e as DataGridCommandEventArgs)

 

dg.edititemindex = e.item.itemindex
dg.databind()
end sub

 

  以上代码需要注意的是,e.item.itemindex就是我们需要编辑的那行数据。在对数据作任何变动以后,都需要重新绑定数据,也就是DataBing()。

 

  OnCancelCommand

 

  取消按钮处理和上面的编辑按钮处理差不多,区别的是,在这里,dg.edititemindex被设为-1,也就是将数据恢复到原来状态。

 

  OnUpdateCommand

 

  先来看数据更新代码:

 

sub dg_update(sender as object, e as DataGridCommandEventArgs)
Dim FNAME As TextBox = e.item.cells(1).controls(0)
Dim LNAME As TextBox = e.item.cells(2).controls(0)
Dim sqlstr As String

 

sqlstr = "UPDATE users SET " & _
"Number1 = '" & FNAME.Text & "', " & _
"Number2 = '" & LNAME.Text & "' " & _
"WHERE Auto = " & e.item.cells(0).text

 

Dim objCommand = New OLEDBCommand(sqlstr, objConn)
objCommand.ExecuteNonQuery()

 

ds.Tables.Clear
objAdapter.Fill(ds, "users")

 

dg.edititemindex = -1
dg.DataBind()
end sub

 

  以上代码将建立两个TextBox,这两个TextBox就是DataGrid中的复本。然后用SQL语句更新数据,最后重新绑定数据。

 

  总结

 

  以上代码可能初学者比较难懂,而且,上面的数据更新方法也不是很好。但是为了我们更好理解,我们还是可以参考以上代码。

 

  六、DataGrid数据排序

 

  数据排序在一些特殊的场合是必要的。下面我们将详细介绍DataGrid中的数据排序功能。在对DataGrid数据实现排序功能以前,我们需要做以下准备:

 

  1、 将AutoGenerateColumns设为打开,这样自定义数据列功能将失去,同时也将失去直接编辑功能。其实这无关紧要的,数据显示和编辑分开不同页面这种模式其实是现在比较认可的方法。

 

  2、 必须将AllowSorting设为真,这样,在每一列数据的标题将建立一个链接,点击这个链接将按照这个字段排序。

 

  3、 必须建立排序事件,也就是OnSortCommand。

 

  现在看代码:

 

<asp:DataGrid id="dg" runat="server"
Bordercolor="black"
gridlines="vertical"
font-names="Arial"
font-size="10pt"
HeaderStyle-BackColor="#FFCC00"
ItemStyle-BackColor="#FFCC66"
AlternatingItemStyle-BackColor="#FFFFFF"
AutoGenerateColumns="True"
OnEditCommand="dg_edit"
OnCancelCommand="dg_cancel"
OnUpdateCommand="dg_update"
OnSortCommand="dg_sort"
AllowSorting="True"
>
</asp:dataGrid>

 

  以下是运行界面:

 

 

 

 

 

  排序事件处理

 

  排序需要用到DataView,现在我们来看排序处理:

 

sub dg_sort(sender as object, e as DataGridSortCommandEventArgs)
Dim dtable as DataTable = ds.Tables("users")
Dim dview as new DataView(dtable)
dview.sort = e.SortExpression.ToString & " ASC"
dg.DataSource = dview
dg.databind()
end sub

 

  从以上代码我们可以发现,数据排序功能的实现是需要依靠DataView的,排序以后,绑定数据。应用Data View还可以实现其他很多功能,我们在这里只介绍它的排序应用。

 

  升序和降序

 

  我们可以给用户选择升序和降序来排列数据:

 

<form runat="server">
<asp:DataGrid id="dg" runat="server"
Bordercolor="black"
gridlines="vertical"
font-names="Arial"
font-size="10pt"
HeaderStyle-BackColor="#FFCC00"
ItemStyle-BackColor="#FFCC66"
AlternatingItemStyle-BackColor="#FFFFFF"
AutoGenerateColumns="True"
OnEditCommand="dg_edit"
OnCancelCommand="dg_cancel"
OnUpdateCommand="dg_update"
OnSortCommand="dg_sort"
AllowSorting="True"
>
</asp:dataGrid>
<p>
<asp:radiobuttonlist runat="server" id="sortby" repeatdirection="horizontal" textalign="right" >
<asp:listitem selected="true">Ascending</asp:listitem>
<asp:listitem>Descending</asp:listitem>
</asp:radiobuttonlist>
</form>
以上大部分代码我们都很熟悉,只是在最后加了两个选项来选择升序还是降序。我们来看事件处理:
sub dg_sort(sender as object, e as DataGridSortCommandEventArgs)
Dim sortby = Request.Form("sortby")
Dim dtable as DataTable = ds.Tables("users")
Dim dview as new DataView(dtable)
If sortby = "Ascending" Then
dview.sort = e.SortExpression.ToString & " ASC"
Else If sortby = "Descending" Then
dview.sort = e.SortExpression.ToString & " DESC"
End If
dg.DataSource = dview
dg.databind()
end sub

 

ADO开发者在操作Recordset 对象的时候,需要知道他们到底需要一个客户端还是服务器端的光标。MoveFirst 或是 AbsolutePosition之类的操作,在服务器端光标的情况下将消耗很大的服务器资源,但在客户端光标的情况下,确是高效和有力的工具。两类光标存在着巨大的差异。一个客户端光标的Recordset 对象事实上更类似于一个高性能的数组,而不是一一种序列化的存取结构。

与之相对,DataSet 始终是'客户端的',并且可以发挥'高性能数组'存取模型的最高效率。在Recordset 中有字段集合,但对于一个Recordset 对象,却没有相应的集合。而DataSet中的所有表都有一个列和一个行的集合,你可以使用简单的随机存取技术来操作它们,表5显示了在ADO.NET 中操作DataSet的对象模型。

通过循环的方式你可以对DataTable中的每一行进行操作,然而我在下一个例子中采用了另一种方法:DataTable 的 Select 方法。这是一个重载方法,从本质上来说,它相当于结合了Recordset的FILTER 和 SORT 属性。SELECT 方法返回一个以DataRow对象为元素的数组--能够利用标准的数组的方法对它处理。需要注意的是所有这些过程是在你程序的缓存中进行的,DataSet 已经和数据源完全的断开了。

下面的示例代码向DataSet中填充两个数据表(第二个表没有使用 WHERE 子句)然后用SELECT 方法从'Authors'返回一个数组,并利用该结果创建一个动态的下拉列表。

Dim dc As New ADODataSetCommand( _
"select au_id, au_fname," & _
" au_lname from authors", strConnect)
Dim ds As New DataSet()

' Declare an array of DataRows
Dim dr() As DataRow
Dim i As Integer

dc.FillDataSet(ds, "Authors")
dc = New ADODataSetCommand( _
"select * from titleauthor", strConnect)
dc.FillDataSet(ds, "Titles")

dr = ds.Tables("Authors").Select( _
"au_lname >= 'R'", "au_lname ASC")

For i = 0 To UBound(dr)
listbox1.Items.Add( _
CStr(dr(i)("au_fname")) & " " _
& CStr(dr(i)("au_lname")))
Next

在这里,SELECT 语句返回所有的行,其中的 last name 的打头字母在 'R'之前,并且对这些行进行了分类,'Titles'表在这里被忽略了

表之间的联系

如果你没有利用SHAPE LANGUAGE 进行过工作,你很可能只是创建一个拥有一个数据表的 DataSet 并对其进行操作,就象Recordset 对象一样。当你一旦向DataSet 中加入了多个表,你会希望在它们之间建立关联以便于操作。在下面的代码中,假定以与上例完全相同的方法创建了一个名为DS的DataSet 对象:

Dim dr() As DataRow
Dim drChildren() As DataRow
Dim dl As DataRelation
Dim i, j As Integer

dl = New DataRelation("AuthorTitles", _
ds.Tables("Authors").Columns("au_id"), _
ds.Tables("Titles").Columns("au_id"))
ds.Relations.Add(dl)

dr = ds.Tables("Authors").Select( _
"au_lname >= 'R'", "au_lname ASC")

For i = 0 To UBound(dr)
listbox1.Items.Add( _
CStr(dr(i)("au_fname")) & " " _
& CStr(dr(i)("au_lname")))
drChildren = dr(i).GetChildRows(dl)
For j = 0 To UBound(drChildren)
listbox1.Items.Add(" " & _
CStr(drChildren(j)("title_id")))
Next
Next

DataSetCommands


表 6:
使用list box显示两个表的一多关系

这段代码在'Authors' 表和 'Titles'表之间建立了一个父子关系的关联,这是通过创建一个DataRelation对象(命名为dl)并将它加入DataSet实现的。关联指定 au_id 为关键字段,通过对子表('Titles')中 au_id 的匹配来得到父表中每一行的子行。在ADO 数据筛选的SHAPE 语言中是,这是通过 RELATE 语句来实现的。

当你指定了父表中的行时,你可以利用这种关联。你可以通过GetChildRows方法得到所有子表中所有相关的行,当然这里的关联关系是由你来决定的。DataRelations 使得创建一个master-detail程序变的非常简单。上面的代码的显示结果见表6。

下面我们来了解一下ADODataSetCommand对象以及与它功能相似的SQLDataSetCommand对象。我们已经了解了它们三个主要功能中的一个,就是通过使用命令字符串和一个连接号向DataSet 对象中加入数据。下面对另外两个主要功能进行讨论,首先是更新(updating)。

在传统的ADO中,一个客户端的 Recordset 对象通过SQL 语句来进行更新。在这里SQL 模拟开放式锁定,因此更新得以被返回到数据库。这是一个灵活的机制,但有两个缺点:一、自动生成的SQL语句不易更改,因此假如你写一些高效率的存储过程,将会比直接使用SQL 语句迅速的多。二、这是第一个问题的延续。当需要更新的数据源无法理解ANSI-SQL的时候,你就无法使用客户端的Recordset了。象Active Directory, Exchange 2000以及 Indexing Services这些兼容ADO 的数据源,它们不兼容ANSI 的标准。因此你如果想通过ADO对它们进行更新,你就只能使用服务器端的光标了。

在ADO.NET 中这些问题被解决了。第一种方法,DataSet 与数据源完全断开,ADODataSetCommand作为一个独立的实体与数据源进行交互。更新完全由ADODataSetCommand进行,而DataSet则被完全隔离。

第二中方法,ADODataSetCommand将更新的SQL语句作为一种公开的属性,这样你可以轻松的替换SQL 语句,或者是存储过程。更为出色的是,如果你想使用存储过程,Visual Studio.NET 将为你生成,在下一部分我们可以看到具体的应用。

最后是关于数据表映射功能。数据的使用者不需要得到这样一个数据表:列以'au_fname' 和 'au_lname'命名。不仅是不美观的问题,更重要的是这样会把数据库的结构暴露出来了,数据映射允许你在DataSet 中替换列的名字,如果需要,可以为不同的用户提供不同的数据表映射,下面我将介绍如何利用Visual Studio.NET ,在图形化的界面下创建数据更新的代码。

简单的可视化设计

Visual Studio.NET 为 Windows Forms, Web Forms, Web Services, Components and XML Schemas的设计提供了图形化的设计工具。设计者只需要从工具条上的控件拖动到工作区域 就可以了。在这里,工作区域将与最终用户看到的界面有很大区别。

当你将一个非可视的对象如ADODataSetCommand拖动进来时,它将被显示在设计视图中,但用户将无法看到这个对象。其他的数据控件也是这样。

表7显示了一个VB.NET的项目,这个项目有一个窗体,上面有一个DataGrid控件、一个CommandButton以及ADODataSetCommand控件,在这里你可以象在Visual Studio 6中一样来处理ADODataSetCommand:在可视化的界面中你可以利用向导来建立ADODataSetCommand的连接字符串,命令字符串;在与数据库的接口上,你可以选择自动生成SQL语句,选择已有的存储过程,或是创建一个新的存储过程。

表8显示了向导的最终结果,你可以给你创建的存储过程命名,或者只是预览一下,然后将之存为文件以便以后修改。

如果你不想利用存储过程,你也可以直接使用SQL语句,你还可以在属性面板上修改这些语句。你还可以做的工作包括给对列进行简单化的命名,以便你今后能够方便的使用。具体的操作可以参看表9的对话框。

在完成了以上的工作后,应用程序的编写变的相对很轻松了,下面是DATAGRID的绑定的代码:

Me.ADODataSetCommand1.FillDataSet(dsAuthors)
Me.DataGrid1.DataSource = dsauthors

ADODataSetCommand1成为窗体Me的一个属性,它将dsAuthors表装入一个DataSet 对象,接着设置DataGrid的DataSource属性为dsAuthors。最后是编写CommandButton的CLICK 事件:

Me.ADODataSetCommand1.Update(dsAuthors)

UPDATE 事件将根据对dsAuthors的修改对数据源进行更新(具体的UPDATE 方法在存储过程中已经被设定)。这与ADO 中断开连接的RecordsetS对象的批量更新很相似,但效率更高。可以在表10中看到最终完成的应用程序,它的列名已经被替换为新的列名。


表10: 运行结果

类型化的DataSet

对于许多开发者来说,他们已经习惯了使用ADO 的 Recordset 对象的,象使用字段(fields)而不是使用属性(properties),这样做有它的优势,但也有很多缺陷。首先,与属性不同,字段并不是强类型的,它不为IntelliSense技术(自动提醒语法、参数和对象属性)所支持。另外,因为不是强类型,所以你无法为它添加自定义的方法或是属性,这意味着当你需要把一个Recordset 对象的功能完全封装起来的时候,你会遇到许多限制。

与之相对,因为.NET 平台支持继承,所以你可以创建DataSet 对象的子类,并向其中添加新的功能。这就是具有类型的 DataSet,它基本上没有什么使用范围的限制,所有DataSet 在.NET 中内建的特性都将被支持,包括绑定,和XML DOM 的内部操作。为了创建这样一个具有类型的 DataSet 对象,你所需要的只是一个XSD 格式的 XML SCHEMA。

当你基于一个DataSetCommand 上创建具有类型的 DataSet 的时候,你甚至可以让Visual Studio.NET 来创建这样一个 XML SCHEMA,所有的工作只是鼠标在'Generate DataSet'菜单上的轻轻一点(见表7)。在这里使用的XML SCHEMA与表2中的是一样的(除非你对数据表的结构做了改动)

在后面的例子中我将使用我创建的具有类型的AuthorsDataSet 对象来代替DataSet 对象。AuthorsDataSet中的所有表和列都将是它的属性,因此所写出的代码将更易于查看,而强类型将更不易出错,同时还可以利用IntelliSense技术。表11显示了类型化的DataSet 的编程界面,注意IntelliSense菜单也被显示出来了。



表11中我们可以看到在AuthorsDataSet被创建之后,同时还创建了authorsSelectTable(继承于DataTable),authorsSelectRow(继承于DataRow),以及所有的列的类(继承于DataColumn),由此,我们可以看到继承对.NET 的重要意义。

FindByAuthor_ID方法自动被添加到authorsSelectTable类中,列属性被自动添加到authorsSelectRow类中,所有的类的代码都是非隐藏的而且易于扩展。如果你已经习惯了使用断开连接的(disconnected)或是虚拟的(fabricated)Recordset 对象,那么转向ADO.NET 使用具有类型的 DataSet 对象是一个很好的选择。

ADO 到 ADO.NET 是一个革命性的发展,在所有的.NET work领域中,许多基本的组件可以被重写,因为不用受到二进制兼容性的强制性约束所以可以对所有类型的组件的接口进行重写和改善,而ADO.NET 只是其中一例。

在经过了几个星期的使用后,我认为 ADO.NET 与ADO 相比是一个更完善的模型,我非常满意它对ADO所做的改进。虽然某种程度上讲,对于开发者来说,需要学习一种新的对象模型,但我仍建议开发者向.NET转移。ADO.NET 继承了ADO的优良特性,并且更易于使用。

 
原创粉丝点击