VB.net数据库编程(09):ADO.net数据接口(下)

前端之家收集整理的这篇文章主要介绍了VB.net数据库编程(09):ADO.net数据接口(下)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
博客升级,打不开,不知道什么原因,

是不是上一篇太长了,于是,我只要分割它到下个了。


上一篇

上篇提到 一个CommandBuilder,这是一个新对象。

它的作用就是:自动生成单表命令,用于将对 DataSet 所做的更改与关联的 sql Server 数据库的更改相协调

因为:da.update()更新命令并“不能”生成 实现DataSet和数据库协调的sql语句.

说白了,DataAdapter只是一个无主意的搬运工,用怎么样的sql语句用到数据库,需要一个“指示”或“指令”

而这个指令或指示就是由CommmandBuilder来说明的,这样搬运工就知道怎么搬进数据库,怎么放好放好(修改)数据。

CommandBuilder具有智能的作用:会自动生成相关的sql语句。所以前面没看到Insert插入sql语句。因为里面有了

newrow,addrow就可以判断是插入记录。

但是,如果设置了 sqlDataAdapter 的 SelectCommand 属性,则可以创建一个 sqlCommandBuilder 对象来自动生成用于

单表更新的 Transact-sql 语句。然后,sqlCommandBuilder 将生成其他任何未设置的 Transact-sql 语句。


每当设置了 DataAdapter 属性sqlCommandBuilder 就将其本身注册为 RowUpdating 事件的侦听器。一次只能将一个

sqlDataAdapter 与一个 sqlCommandBuilder 对象(或相反)互相关联。


为了生成 INSERT、UPDATE 或 DELETE 语句,sqlCommandBuilder 会自动使用 SelectCommand 属性来检索所需的元数据集。

如果在检索到元数据后(例如在第一次更新后)更改 SelectCommand,则应调用 RefreshSchema 方法来更新元数据。


SelectCommand 还必须至少返回一个主键列或唯一的列。如果什么都没有返回,就会产生 InvalidOperation 异常,不生成命令。


sqlCommandBuilder 还使用由 SelectCommand 引用的 Connection、CommandTimeout 和 Transaction 属性。如果修改

这些属性中的一个或多个,或者替换了 SelectCommand 本身,用户则应调用 RefreshSchema。否则,InsertCommand、

UpdateCommand 和 DeleteCommand 属性都保留它们以前的值。


如果调用 Dispose,则会解除 sqlCommandBuilder 与 sqlDataAdapter 的关联,并且不再使用生成的命令。


例子:前一例子是插入,现在用一个修改

界面基本一下,就是按键代码变换一下。

需要说明的是:DataAdapter是一个呆板的搬运工,当搬运到内存中的DataSet的表是没有主键设置的,所以要操作时需要设置。

另外一个是,要定位到一个Row中,用一个Find()方法


  1. PrivateSubButton1_Click(senderAsObject,eAsEventArgs)HandlesButton1.Click
  2. DimcnAsNewsqlConnection("DataSource=(local);InitialCatalog=Sales;IntegratedSecurity=False;UserID=sa;Password=123456;")
  3. DimdaAsNewsqlDataAdapter("select*fromgrade",cn)'搬运工拉好水
  4. DimdsAsNewDataSet()'本地内存准备好容器来装水
  5. da.Fill(ds,"mytable")'装水
  6. DimdrowAsDataRow'定义行变量
  7. ds.Tables("mytable").PrimaryKey=NewDataColumn(){ds.Tables("mytable").Columns("学号")}'设置内存表中的主键
  8. drow=ds.Tables("mytable").Rows.Find(TextBox1.Text)'根据学号定准到对应行
  9. Try
  10. drow("学号")=TextBox1.Text'对应行赋值
  11. drow("姓名")=TextBox2.Text
  12. drow("语文")=TextBox3.Text
  13. drow("数学")=TextBox4.Text
  14. drow("英语")=TextBox5.Text
  15. DimcmdbAsNewsqlCommandBuilder(da)'和数据库打个电话,本地内存有水要运过去
  16. da.Update(ds,0); background-color:inherit">'上面电话里已经说好了,现在把水运到数据库
  17. DataGridView1.DataSource=ds.Tables("mytable")'绑定到控件上显示当前结果
  18. CatchexAsException
  19. MessageBox.Show(ex.ToString)
  20. EndTry
  21. EndSub

注1:Rows.Find(object),默认提查找主键,当是主键是一个字段时,直接用这个字段。

注2:Rows.Find(object[]),主键是多个字段组成,则用几个字段来组成。用数组来表示,每个元素一个字段名,参数用数组名。



4.4 DataAdapter的Command属性

DataAdapter对象通过4个属性传递数据。

这四个属性必须是Command对象:SelectCommand,InsertCommand,UpdateCommand,DeleteCommand四个对象

如果是查询则是SelectCommand

如果是非查询是其余三个:插入、更新、删除

下例中就是da.SelectCommand,因为sql是select,


?@H_720_403@ @H_163_404@
    ImportsSystem.Data.sqlClient
  1. PublicClassForm1
  2. DimcnAsNewsqlConnection("DataSource=.;InitialCatalog=Sales;IntegratedSecurity=False;UserID=sa;Password=123456;")
  3. DimcmdAsNewsqlCommand("select*fromgrade",cn)
  4. DimdaAsNewsqlDataAdapter
  5. da.SelectCommand=cmd
  6. cn.Open()
  7. DimdsAsNewDataSet
  8. da.Fill(ds,"grade")
  9. DataGridView1.DataSource=ds.Tables("grade")
  10. EndSub
  11. EndClass


注1:默认下,Connection的OPen()方法,DataAdapter自动调用SelectCommand属性

除了SelectCommand属性,其它3个需要使用ExecuteNonQuery()方法调用

注2:例中没有用cn.open,这是因为Fill有自动打开连接的功能

Fill 方法使用 SELECT 语句从数据源中检索数据。与 Select 命令关联的 IDbConnection 对象必须有效,但不需要将其

打开。如果调用 Fill 之前 IDbConnection 已关闭,则将其打开以检索数据,然后再将其关闭。如果调用 Fill 之前连接

已打开,它将保持打开状态。


如果命令不返回任何行,则不向 DataSet 中添加表,并且不引发异常。


如果 DbDataAdapter 对象在填充 DataTable 时遇到重复列,它将以“columnname1”、“columnname2”、“columnname3”

这样依次排序的模式命名后面的列。如果传入数据包含未命名的列,它们将按“Column1”、“Column2”的模式放在 DataSet 中。


当指定的查询返回多项结果时,每个结果集都放置在单独的表中。将整数值追加到指定的表名从而对其他结果集进行

命名(例如“Table”、“Table1”、“Table2”等)。如果某个查询不返回行,则不会为该查询创建表,因此,如果您先处理一个

插入查询,然后再处理一个选择查询,那么由于为选择查询创建的表是第一个表,所以该表将被命名为“Table”。使用列名和

表名的应用程序应确保一定不要与这些命名模式发生冲突。


Fill 方法支持以下情况:DataSet 包含多个 DataTable 对象,而这些对象的名称只有大小写不同。在这种情况下,Fill 执行区分

大小写的比较以查找相应的表,如果不存在完全匹配的表,则新建一个。



例子:上面DataSet中,用DataAdapter来填充一个表,下面用来填充几个表。

注意每个表使用的Command对象,和实现过程。

对于ExecuteNonQuery必须是先有连接打开(cn.open),而selectCommand不必这样,所以cn.open在第二个之前,必须存在。

?@H_720_403@
    DimInsertcmdAsNewsqlCommand("insertintograde(学号,姓名,数学)values(111,'盖茨',59)",85); line-height:18px"> DimSelectcmdAsNewsqlCommand("select*fromgradewhere学号=111",cn)
  1. DimUpdatecmdAsNewsqlCommand("updategradeset数学=60where学号=111",226); color:inherit; line-height:18px"> da.SelectCommand=Selectcmd
  2. da.UpdateCommand=Updatecmd
  3. da.InsertCommand=Insertcmd
  4. DimdsAsNewDataSet
  5. "grade1")
  6. da.InsertCommand.ExecuteNonQuery()
  7. "grade2")
  8. da.UpdateCommand.ExecuteNonQuery()
  9. "grade3")
  10. DataGridView1.DataSource=ds.Tables("grade1")
  11. DataGridView2.DataSource=ds.Tables("grade2")
  12. DataGridView3.DataSource=ds.Tables("grade3")
  13. EndClass


品味里面的cn.open位置。第一个fill没有打开连接,所以fill会自动连接,获取数据集后,再关闭

第二和第三个fill因连接打开了,所以fill进,直接获取数据集,最后保持前面的状态,即保持连接。

所以有时为了性能,最好从开始一直打开,到最后得到结果后,再关闭


注1: 第一个表没记录,因为没查出这个记录。第一个Fill默认用的是SelectCommand。

第二个只有一个记录,用的Insert,返回的是影响的记录,影响的是一条,所以显示一条

第三表只有一个记录,用的Update,返回影响的记录,影响仍是一条,所以显示一条。

注2:在填充(多个表)在一个DataSet中时

如果在填充数据表时遇到错误或异常,则错误发生之前添加的行将保留在数据表中。操作的剩余部分被中止。

当用于填充 DataSet 的 SELECT 语句(例如批处理 sql 语句)返回多项结果时,请注意以下事项:•
如果其中一项结果包含错误,则将跳过所有后面的结果而不将其添加到 DataSet 中。

当使用后面的 Fill 调用来刷新 DataSet 的内容时,必须满足以下两个条件:
1.该 sql 语句应该与最初用来填充 DataSet 的语句匹配。
2.必须存在键列信息。如果主键信息存在,则协调任何重复的行,并且这些重复行将只在与 DataSet 对应的

DataTable 中出现一次。可以通过 FillSchema(通过指定 DataTable 的 PrimaryKey 属性),

或者通过将 MissingSchemaAction 属性设置为 AddWithKey 来设置主键信息。

如果 SelectCommand 返回 OUTER JOIN 的结果,则 DataAdapter 不为生成的 DataTable 设置 PrimaryKey 值。必须显式

定义主键,确保正确地解析重复行。(前面有例子设置主键的情况)



5、DataSet对象

水厂(数据库)<--------搬运工(DataAdapter)fill----------->用户家中水缸(DataSet)

水缸的作用就是离线技术,它独立于数据库用户可以任意操作它,必要时,还可使用搬运工返回水厂(现实中是不行的)

DataSet相当于用户本机内存中的数据库,它采用XML描述,所以可以描述复杂关系。

DataSet还可以装很多个表,还有可以装表间的关系、约束等。它提供了一致的关系编程模型。

DataSet的重要对象如下:

1、TableCollection对象:即DataTable,可含多个,每个DataTable都含一个ColumnsCollection和一个RowsCollection,所以不用New它。

2、RelationsCollection对象:各DataTable之间关系通过DataRelation来表达,它的集合就是RelationsCollection对象。

3、ExtendedProperties对象:用来定义特定的信息,比如密码、更新时间等。


总之,DataSet是用户手中的“数据库”,可以任意来操作它,其表名也是可以自己定义的,同时它还可以再次返回到原来服务器上的数据库 中。


下面例子,只玩自家中的水缸,与服务器上数据库无没有一点关系 。

水缸----》里面有很多分格的小水缸(表)----》小水缸中有行集合和列集体。

由行-->行集合 ,添加到表集合--->再添加到水缸中。

?@H_720_403@
    PublicClassForm1
  1. DimdsAsNewDataSet'建立水缸
  2. DimdtAsNewDataTable("Squ")'建立水缸中的分格容器即表,表名:Squ
  3. '不能new,因为分格容器中含一个列和一个行对象
  4. dt.Columns.Add(NewDataColumn("数字",GetType(Integer)))'添加一列
  5. dt.Columns.Add(NewDataColumn("平方",GetType(Integer)))
  6. DimiAsInteger
  7. Fori=3To10
  8. drow=dt.NewRow'表中新增空行,下面赋值
  9. drow("数字")=i'或drow(0)
  10. drow(1)=i*i
  11. dt.Rows.Add(drow)'新行进入表中
  12. Next
  13. ds.Tables.Add(dt)'把这个已经有“内容”的表,填充到水缸中
  14. DataGridView1.DataSource=ds.Tables("Squ")
  15. EndSub
  16. EndClass


注:上例 最后添加一个保存到文件代码

ds.WriteXml("D:\Squ.xml")

即把DataSet保存到XML文件中,打开这个文件如下:



对于DataSet中的表,也可以用视图方式,视图DataView对象


在DataSet的DataTable上建立DataView。

DataView对象定义了DataTable的数据查看方式。数据默认的查看方式 是将数据以表格的形式排列,

且数据排列的顺序遵循从数据库表中取出数据时排列的顺序,通过DataView对象合数据按照某些规则显示

下例是一个查找


?@H_720_403@
    PrivateSubButton1_Click(senderAsObject,eAsEventArgs)HandlesButton1.Click
  1. DimcnAsNewsqlConnection("DataSource=.;InitialCatalog=Sales;IntegratedSecurity=False;uid=sa;Password=123456;")
  2. DimcmdAsNewsqlCommand("select*fromgrade",226); color:inherit; line-height:18px"> DimdaAsNewsqlDataAdapter
  3. da.SelectCommand=cmd
  4. DimdvAsNewDataView(ds.Tables("grade"))
  5. dv.RowFilter="数学>60"
  6. dv.Sort="数学desc,英语"
  7. DataGridView1.DataSource=dv
  8. cn.Close()
  9. EndClass


过滤条件由RowFilter指出,排列顺序由Sort指出。

DataView是本地内存中的视图,所以效率非常高,查询、排序等直接在内存中进行,不用与数据库进行数据交换。

DataView的构造函数有三个:

1、无参,空的视图

2、带一个参数的,就上例,直接带表集合;

3、带四个参数,即DataView(table As DataTable,RowFilter As String,Sort As String,RowState As DataViewRowState)

前三个分别为表集合、过滤条件、排序,形式如上例所表。最后一个是RowState。

最后一个是行的状态的过滤。比如,指明是新加入的行,则表中为新加入的行;如果指明是修改的行,则过滤为修改过的行。

几个值:CurrentRows 当前所有行(含未修改、新加入、已经修改的行)

Added 新加入的行

ModifiedCurrent、ModifiedOriginal 修改的行(前一个表示动过,后一个表示相对最原始数据有改变)

(比如原行数据是35,修改成34,再改回去35,则表示动过,但相对原始数据没修改

这个几个值可以用and,or等进行合并等


?@H_720_403@
    DimdvAsNewDataView(ds.Tables("grade"),"","姓名",DataViewRowState.CurrentRows)'指定默认查找列为姓名
  1. DimrowIndexAsInteger=dv.Find(TextBox1.Text)
  2. IfrowIndex=-1Then
  3. Label1.Text="没相关记录"
  4. Else
  5. Label1.Text=dv(rowIndex)("姓名").ToString&""&dv(rowIndex)("语文").ToString&""&dv(rowIndex)("数学").ToString
  6. EndIf
  7. cn.Close()
  8. EndClass



5个关键对象已经完毕。

基本上前面的重复。有些细节可能新的。

唯一注意有一个事务:开始、提交、回滚,新东西,不过个东西,好像用得不多。

猜你在找的VB相关文章