2 获取数据
连接数据库之后,就可以从数据库中提取数据了。在示例程序中,点击“从数据库获取数据”按钮,可以看到状态栏上的提示信息——“数据已取回,共324条”。
图 5?10 获取数据
提取数据也是个较复杂的过程,需要有好几个对象通力协作才能完成。
(1)定义一个OleDbDataAdapter对象,这个对象负责从数据库中提取数据:
Private da As OleDbDataAdapter = Nothing
(2)定义一个OleDbCommand对象,此对象负责向数据库发送SQL命令:
Private comm As OleDbCommand = Nothing
(3)定义一个DataTable对象,此对象用于存放数据,相当于数据库中的表。
Private dt As DataTable
这三个对象加上前面介绍的OleDbConnection对象,就可以实现数据的提取。这是由Sub过程OnGetData()实现的:
1 Private Sub OnGetData()
2 If da Is Nothing Then
3 da = New OleDbDataAdapter
4 End If
5
6 If comm Is Nothing Then
7 comm = New OleDbCommand
8 comm.Connection = conn '指定连接对象
9 comm.CommandType = CommandType.Text '指明使用SQL命令
10 comm.CommandText = "Select * from Client" '指定SQL命令内容
11 End If
12 '将OleDbCommand对象与OleDbDataAdapter对连接起来。
13 da.SelectCommand = comm
14
15 If dt Is Nothing Then
16 '创建一个DataTable对象,存放从数据库中取出来的数据
17 dt = New DataTable
18 End If
19
20 '填充数据
21 da.Fill(dt)
22
23 '激活“在网格中显示记录”按钮
24 Me.btnShowDataInGrid.Enabled = True
25
26 '显示信息
27 Me.StatusBar1.Text = "数据已取回,共" & dt.Rows.Count & "条"
28
29 End Sub
注意第8句,第13句和第21句,这三条语句实现了对象之间的合作。
第8句的含义是OleDbCommand对象采用OleDbConnection对象连接数据库,通过这一连接向数据库发送SQL命令。
第13句表明OleDbAdapter对象使用OleDbCommand对象向数据库发送提取数据的“Select …”命令。
第21句表明OleDbAdapter对象将取回的数据放到DataTable对象中。
这四个对象之间的关系可以用以下图进行说明:
图 5?11 ADO.NET对象的合作关系
图 5?11 中,程序向数据库发送的各种命令(比如连接数据库,执行SQL命令等)被称为“命令流”,可以看到命令主要由OleDbAdapter负责确定,它委托OleDbCommand对象执行此特定的命令,而OleDbCommand需要通过OleDbConnection对象与数据库连接上之后,再把此命令传给数据库本身,由数据库管理系统(DBMS)执行此命令。
如果被执行的命令是一条提取数据的命令,则数据库会把需要的数据准备好,通过OleDbConnection对象建立的连接传给OleDbAdapter,由它负责把数据“塞入”DataTable对象中。被传送的数据在图 5?11中被称为“数据流”,以虚线表示。传送数据的终点站是DataTable中,而OleDbAdapter可以看成是一个数据的中转站,其Fill方法将收到的数据再转给DataTable对象。一旦数据从数据库“搬家”到DataTable之后,这些数据就自立门户,与数据库“老家”中的数据没有任何联系了。
提示:
此处只是简单介绍了一种最常见的数据流动情况,更完整详细的介绍请参见第七章。
3 显示记录
数据到达DataTable之后,并不能自动地显示在窗体上,这是因为DataTable是个非可视的对象。
在示例程序中点击“在网格中显示记录”,运行结果如图 5?12所示。
图 5?12 显示数据
将DataTable中的数据显示在可视化控件DataGrid中是通过以下代码实现的:
DataGrid1.DataSource = dt
通过设定DataGrid对象的DataSource属性为DataTable,就在DataTable与DataGrid中建立了一种关联,DataTable中数据的任何变化都会同步地在DataGrid中显示,同样的,用户也可以通过DataGrid来直接修改数据,他所做的所有修改都会被保存到DataTable中。
有个专门的术语用于描述DataTable与DataGrid之间建立的这种关联,这就是“数据绑定(DataBinding)”。
数据绑定是个非常重要的概念,将在7.5节中对这一概念的真正含义作完整的解释。
4 编辑与修改记录
任何一个数据库应用程序,如果只能显示数据而不能增删改数据,都是用途有限的。.NET所提供的DataGrid是一个功能强大的数据绑定控件,直接支持对记录的增加、删除与修改。
图 5?13 修改
如图 5?13 所示,在网格中点击某个单元格,就可以直接修改这一字段的内容,并在当前行左端显示一支小铅笔图标。
直接点击最后一行的任意单元格,输入新值,就可以新增记录,如图 5?14所示:
图 5?14 新增记录
点击最左边的一列,可以选中一行,再按键盘上的“DEL”键,可以删除记录。
图 5?15 选中一行记录删除
虽然通过DataGrid可以对记录进行增、删、改,但如果这时直接关闭程序,当再次运行程序时,会发现所做的修改都没有被保存。其原因何在?
修改不能保存的最根本原因是数据一旦从数据库中取出,这些数据独立于数据库了,换言之,取出的数据存放在内存中,对它的修改不会导致数据库的内容随之改变。这种数据独立性给我们带来了很大的灵活性。
注意:
VB6中使用DataGrid显示数据库中数据时,其增删改会直接保存到数据库中,即在任何时候,在窗体上看到的数据就是数据库中的数据(除非采用了“断开”方式)。VB6所使用的数据库技术是ADO,而VB.NET使用的是ADO.NET,两者有着根本的不同。VB6程序员要注意这个重要的区别。
但确实需要将修改后的数据永久保存,为此,可以使用OLEDBDataAdapter对象的Update()方法实现此功能。
试一试:
在示例程序中,给“保存”按钮的单击事件加入下面一句:
'将更改保存到数据库中
da.Update(dt)
然后运行程序,随意修改、删除或增加几条记录,单击“保存”按钮。观察运行情况。
可以看到,直接调用Update()方法时,会引发一个异常,如 图 5?15 所示:
图 5?16 更新异常其原因何在?
数据的提取与保存都是由OLEDBDataAdapter负责的,它通过四个OLEDBCommand对象类型的属性来完成四种典型的数据处理任务:
提取记录:SelectCommand
新增记录:InsertCommand
删除记录:DeleteCommand
修改记录:UpdateCommand
当我们从数据库中提取记录时,已向OLEDBDataAdapter传入了一个OLEDBCommand对象,其执行的SQL命令是:
Select * from Client
但我们并没有给其它三个操作提供有效的OLEDBCommand对象,所以,在示例程序中OLEDBDataAdapter无法保存数据。
OLEDBCommand对象是专用于执行SQL命令的,InsertCommand执行SQL中的Insert命令,DeleteCommand执行SQL中的Delete命令, UpdateCommand执行SQL中的Update命令。
提示:
在第六章中,将介绍SQL的常用命令,学会编写SQL语句完成许多数据处理工作。
可以手动地创建OLEDBCommand对象并设置其SQL命令,然后把它传给OLEDBDataAdapter对象,但这是一个麻烦且易出错的工作,.NET提供了一个OleDbCommandBuilder类来完成此工作。参见以下代码:
Private cb As OleDbCommandBuilder
'保存数据
Private Sub OnSaveData()
If cb Is Nothing Then
cb = New OleDbCommandBuilder
cb.DataAdapter = da
'设定更新命令
da.UpdateCommand = cb.GetUpdateCommand
'设定插入命令
da.InsertCommand = cb.GetInsertCommand
'设定删除命令
da.DeleteCommand = cb.GetDeleteCommand
End If
'将更改保存到数据库中
da.Update(dt)
End Sub
请注意上面的代码中没有看到设置OLEDBDataAdapter对象的SelectCommand属性的语句,这是因为这一属性在提取数据时就已经设置了。
在单击“保存”按钮时调用上述Sub过程,数据便可以正确地保存到数据库中。
图 5?17 将数据保存到数据库中
至此,一个功能基本完备的数据库应用程序已开发完成。
看上去,一切并不复杂。但在简单的背后,是由复杂的技术做支撑的,一切并不“简单”。
5 小结
通过开发一个小的数据库应用程序,读者应该对.NET中如何开发数据库应用程序有了一个总体的认识,但这个小程序的功能还是很有限的,比如没有查找数据的功能,而且过多地依赖于DataGrid这一功能强大的控件,它把许多技术细节给封装了起来。不管我们的这个小程序多么简陋,这都是一个很好的起点。
“盲人摸象”是一个众人熟知的成语,由于软件技术系统的庞大与复杂,自学过程就是“盲人摸象”的过程。“盲人摸象”学到的东西是片面的,局部的,是应该尽力避免出现的情况。
如果把.NET数据库编程看作一头“大象”,那么,这一章的目的就是先让读者初步地了解大象是个什么样的,有了个总体印象,然后我们再用放大镜去仔细研究“大象”的每个局部,了解清楚之后,再从总体上对大象整体进行进一步的概括。通过这种方法,就可以把“大象”研究透了,“盲人摸象”的情况就不会发生。
在后面的几章中,将详细解析数据库编程的各个方面,读者通过后几章的学习,将会深入地把握ADO.NET内部的运行机理,极大地增强开发数据库应用程序的能力。
-----------------------------------------------------------------------------------
转载请注明出处及作者。