本文共 10892 字,大约阅读时间需要 36 分钟。
DataAdapter与数据源提供程序相关,,命名空间为System.Data.OleDb,相应的DataAdapter对象在System.Data.OleDb空间里对应的是OleDbDataAdapter对象。
而DataTable对象和DataSet对象同属于System.Data命名空间,可见其与数据源无关。DataTable对象可作为DataSet对象中的表,也可以单独作为数据集。 体系结构。 使用OleDbDataAdapter对象的Fill方法可从数据源检索数据并填充 DataSet 中的表,实例化OleDbDataAdapter对象时必须设置其SelectCommand属性。 使用OleDbDataAdapter对象的Update方法还可将对 DataSet 所做的更改解析回数据源,实例化OleDbDataAdapter对象时必须设置InsertCommand、 UpdateCommand或 DeleteCommand属性。一、OleDbDataAdapter对象填充数据集并将更改保存到数据库
以下示例代码演示使用OleDbDataAdapter对象填充数据集,修改数据集中的表数据,然后将修改过的数据更新到数据库。
Imports System.Data.OleDbPublic Class Form2 Private Const strconn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\test.accdb" Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load '连接数据库 Dim conn As New OleDbConnection(strconn) '打开数据库 conn.Open() '实例化OleDbDataAdapter Dim adapter As New OleDbDataAdapter("SELECT stutbl.* FROM stutbl", conn) '实例化DataSet Dim dst As New DataSet("mydst") '添加表 dst.Tables.Add("mytbl") '填充数据到DataSet adapter.Fill(dst, "mytbl") '窗口显示数据 DataGridView1.DataSource = dst.Tables("mytbl") '操作数据表DataTable With dst.Tables("mytbl") '插入行 Dim newrow As DataRow = .NewRow() newrow("stuname") = "李四" newrow("sex") = "男" newrow(3) = "二年级" .Rows.Add(newrow) '更新行 .Rows(2)("stuname") = "王二" '删除行 .Rows(.Rows.Count - 2).Delete() End With '添加insert命令参数 Dim insertcmd As New OleDbCommand("Insert INTO stutbl(sex,stuname,grade) VALUES (?,?,?)", conn) insertcmd.Parameters.Add("@sex", OleDbType.VarChar, 1, "sex") insertcmd.Parameters.Add("@stuname", OleDbType.VarChar, 10, "stuname") insertcmd.Parameters.Add("@grade", OleDbType.VarChar, 10, "grade") adapter.InsertCommand = insertcmd '添加update命令参数 Dim updatecmd As New OleDbCommand("Update stutbl set sex=?,stuname=?,grade=? Where ID=?", conn) updatecmd.Parameters.Add("@sex", OleDbType.VarChar, 1, "sex") updatecmd.Parameters.Add("@stuname", OleDbType.VarChar, 10, "stuname") updatecmd.Parameters.Add("@grade", OleDbType.VarChar, 10, "grade") updatecmd.Parameters.Add("@ID", OleDbType.VarChar, 10, "ID").SourceVersion = DataRowVersion.Original adapter.UpdateCommand = updatecmd '添加delete命令参数 Dim deletecmd As New OleDbCommand("Delete * FROM stutbl Where ID=?", conn) deletecmd.Parameters.Add("@ID", OleDbType.BigInt, Nothing, "ID").SourceVersion = DataRowVersion.Original adapter.DeleteCommand = deletecmd Dim dstchanges As DataSet '检查数据是否发生更改 If dst.HasChanges Then '将更改的行保存到新数据集中 dstchanges = dst.GetChanges() '将更改显示到窗口 DataGridView2.DataSource = dstchanges.Tables("mytbl") '检查发生更改的行是否有错误 If dstchanges.HasErrors() Then '拒绝更改 dst.RejectChanges() Else '更新数据库 adapter.Update(dstchanges, "mytbl") End If End If '关闭数据库 conn.Close() End SubEnd Class
代码解读:
1、操作数据表部分代码,如添加新行、更新行数据、删除行等可以不用,直接在DataGridView控件修改数据即可即时反映回数据集。写这部分代码主要是为了做笔记。 需要特别注意的是删除行的方法有两个:Delete方法和Remove方法。 Delete方法只是把该行的行状态修改为Deleted,此行还在数据集中,并没有真正的删除。可以使用DataAdapter的update方法来删除数据库中对应的这一行。 Remove方法是真的把该行从数据集移除了,此行真的不在数据集中,使用DataAdapter的update方法时不会删除数据库中对应的这一行的。 2、为命令添加参数的语句,如updatecmd.Parameters.Add("@sex", OleDbType.VarChar, 1, "sex")
第一个参数"@sex"是Parameter的名称,可以自由发挥,但为了更好解读代码,最好对应数据集中的列名,最后一个参数"sex"是指这个参数的值从数据集中的"mytbl"表的sex列取值,这个不是数据库中的列,需要特别注意。
3、添加update命令和delete命令参数时需要设置主键列的SourceVersion属性值为DataRowVersion.Original,这是表示取从数据库加载时的值,也就是添加到数据集中最原始的值。因为可能在数据集中修改了该主键的值,这样的话就没办法在数据库找到该主键值或找错,造成更新出错。相关内容可以参阅官网帮助《》二、OleDbCommandBuilder 对象自动生成更新命令的SQL语句
看着为命令添加参数的代码就头痛,好哆嗦,其实也有简洁的方法。
可以把这一长串代码:'添加insert命令参数 Dim insertcmd As New OleDbCommand("Insert INTO stutbl(sex,stuname,grade) VALUES (?,?,?)", conn) insertcmd.Parameters.Add("@sex", OleDbType.VarChar, 1, "sex") insertcmd.Parameters.Add("@stuname", OleDbType.VarChar, 10, "stuname") insertcmd.Parameters.Add("@grade", OleDbType.VarChar, 10, "grade") adapter.InsertCommand = insertcmd '添加update命令参数 Dim updatecmd As New OleDbCommand("Update stutbl set sex=?,stuname=?,grade=? Where ID=?", conn) updatecmd.Parameters.Add("@sex", OleDbType.VarChar, 1, "sex") updatecmd.Parameters.Add("@stuname", OleDbType.VarChar, 10, "stuname") updatecmd.Parameters.Add("@grade", OleDbType.VarChar, 10, "grade") updatecmd.Parameters.Add("@ID", OleDbType.VarChar, 10, "ID").SourceVersion = DataRowVersion.Original adapter.UpdateCommand = updatecmd '添加delete命令参数 Dim deletecmd As New OleDbCommand("Delete * FROM stutbl Where ID=?", conn) deletecmd.Parameters.Add("@ID", OleDbType.BigInt, Nothing, "ID").SourceVersion = DataRowVersion.Original adapter.DeleteCommand = deletecmd
用如下代码替换:
Dim builder As OleDbCommandBuilder = New OleDbCommandBuilder(adapter) builder.GetUpdateCommand() builder.GetDeleteCommand() builder.GetInsertCommand()
OleDbCommandBuilder 对象可以自动生成OleDbDataAdapter对象的DeleteCommand 、 InsertCommand和UpdateCommand 命令 。
但使用OleDbCommandBuilder时需注意: 1、数据集必须是单个数据库表中生成,也就是说只能更新单个表。 2、为了能够自动生成命令,必须设置 SelectCommand 属性,这是最低要求。SelectCommand 还必须至少返回一个主键或唯一列。 如果不存在任何主键和唯一列,则会生成 InvalidOperation 异常,并且不会生成命令。 3、如果您在自动生成 INSERT、UPDATE 或 DELETE 命令后修改 SelectCommand,则可能会发生异常。为避免出错,可以通过调用 OleDbCommandBuilder 的 RefreshSchema 方法来刷新由OleDbCommandBuilder。三、将数据库表架构填充到数据集中
连续使用OleDbDataAdapter对象Fill方法填充数据集,因为没有主键(唯一)约束,刷新数据时可能会出现数据重复,如:
可以先使用OleDbDataAdapter对象FillSchema方法自动将数据库中的表架构填充到数据集中,然后再用Fill方法将数据填充到数据集。adapter.FillSchema(dst.Tables("mytbl"), SchemaType.Mapped)adapter.Fill(dst, "mytbl")
有了主键约束就不会出现重复数据了,但这只能用于单表查询结果集,如果是多表查询结果集只能自定义数据集中的表架构了。
其实也有简单方法:先使用DataTable的Clear方法清除表内的所有数据,然后再调用OleDbDataAdapter对象Fill方法重新填充(即刷新数据)DataTable,这样就不会有重复数据出现了,如:dst.Tables("mytbl").Clear()adapter.Fill(dst, "stutbl")
使用DataSet对象的Clear方法可以清除DataSet数据集中所有表内的所有数据行。
四、自定义表构架并将数据库数据填充到数据集
Public Class Form2 Private Const strconn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\test.accdb" Private dst As DataSet Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load dst = New DataSet() '添加表 Dim dt As DataTable = dst.Tables.Add("mytbl") '添加列 dt.Columns.Add("stsex", Type.GetType("System.String")) dt.Columns.Add("stgrade", Type.GetType("System.String")) dt.Columns.Add("stname", Type.GetType("System.String")) '添加自增长和主键 Dim coldi As DataColumn = dt.Columns.Add("di", Type.GetType("System.Int32")) coldi.AutoIncrement = True '设置为自增长列 '添加主键约束 Dim columns(0) As DataColumn columns(0) = coldi dt.PrimaryKey = columns '自定义DataGridView列 DataGridView1.AutoGenerateColumns = False '不自动创建列 DataGridView1.DataSource = dt '数据源 Dim colID As New DataGridViewTextBoxColumn() colID.DataPropertyName = "di" colID.HeaderText = "编号" colID.Name = "ID" DataGridView1.Columns.Add(colID) Dim colname As New DataGridViewTextBoxColumn() With colname .DataPropertyName = "stname" .HeaderText = "姓名" .Name = "stuname" End With DataGridView1.Columns.Add(colname) Dim colsex As New DataGridViewTextBoxColumn() With colsex .DataPropertyName = "stsex" .HeaderText = "性别" .Name = "stusex" End With DataGridView1.Columns.Add(colsex) Dim colgrade As New DataGridViewTextBoxColumn() With colgrade .DataPropertyName = "stgrade" .HeaderText = "年级" .Name = "stugrade" End With DataGridView1.Columns.Add(colgrade) End Sub '查询数据库填充数据集并显示到窗体 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click '连接数据库 Dim conn As New OleDbConnection(strconn) '打开数据库 conn.Open() '实例化OleDbDataAdapter Dim strSQL As String = "SELECT studenttbl.ID as di,studenttbl.stuname as stname, sextbl.sex as stsex, gradetbl.grade as stgrade" _ & " FROM sextbl,studenttbl,gradetbl" _ & " WHERE (([studenttbl].[gradeID]=[gradetbl].[gradeID]) AND ([studenttbl].[sexID]=[sextbl].[sexID]));" Dim adapter As New OleDbDataAdapter(strSQL, conn) '填充数据到DataSet dst.Tables("mytbl").Columns("di").AutoIncrement = False adapter.Fill(dst, "mytbl") dst.Tables("mytbl").Columns("di").AutoIncrement = True '关闭数据库 conn.Close() End SubEnd Class
将数据集声明为公有变量并在加载窗体时自定义表架构,特别注意的是在设置SelectCommand命令的SQL语句时,查询结果集各列名称要与数据集定义的列名称相同。
五、使用ColumnMappings关联OleDbDataAdapter与DataTable间的列
如果查询结果集各列名称与数据集定义的列名称不相同的话,还可以这样处理:使用OleDbDataAdapter的TableMappings属性来关联DataSet中DataTable名称与OleDbDataAdapter源表名称,然后再使用DataTableMapping的ColumnMappings属性来关联DataTable与OleDbDataAdapter各列名称。
把按钮Button1的单击事件代码修改如下:Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click '连接数据库 Dim conn As New OleDbConnection(strconn) '打开数据库 conn.Open() '实例化OleDbDataAdapter Dim strSQL As String = "SELECT studenttbl.ID,studenttbl.stuname, sextbl.sex, gradetbl.grade" _ & " FROM sextbl,studenttbl,gradetbl" _ & " WHERE (([studenttbl].[gradeID]=[gradetbl].[gradeID]) AND ([studenttbl].[sexID]=[sextbl].[sexID]));" Dim adapter As New OleDbDataAdapter(strSQL, conn) Dim mapping As System.Data.Common.DataTableMapping = adapter.TableMappings.Add("stutbl", "mytbl") '关联表名 '关联列名 mapping.ColumnMappings.Add("ID", "di") mapping.ColumnMappings.Add("stuname", "stname") mapping.ColumnMappings.Add("sex", "stsex") mapping.ColumnMappings.Add("grade", "stgrade") '填充数据到DataSet adapter.Fill(dst, "stutbl") '关闭数据库 conn.Close() End Sub
写在最后:
1、调用OleDbDataAdapter对象Fill方法时,不需要手工打开OleDbConnection。
如果OleDbDataAdapter对象的SelectCommand属性的OleDbConnection已经关闭,OleDbDataAdapter将自动打开连接、提交查询、提取结果,然后关闭OleDbConnection。但是如果在调用Fill方法之前已经打开OleDbConnection,调用以后OleDbConnection仍然处于打开状态。
如果用多个OleDbDataAdapter对象将多个查询的结果填充到DaraSet中,不手动打开OleDbConnection的话,每次都调用OleDbDataAdapter对象的Fill方法都会打开和关闭OleDbConnection,为了避免重复地多次打开和关闭OleDbConnection对象,在对OleDbDataAdapter对象调用Fill方法之前,先调用OleDbConnection对象的Open方法。填充数据结束后调用OleDbConnection对象的Close方法关闭OleDbConnection。如:'打开数据库conn.Open()adapter.Fill(dst, "stutbl")adapter1.Fill(dst, "stutbl")'关闭数据库conn.Close()
2、ACCESS每次只能执行一条SQL语句,所以当然不会支持逻辑语句,也就写不出真正意义的存储过程。
如果试图在SelectCommand等属性里设置多条SQL语句会报错,提示“System.Data.OleDb.OleDbException:“在 SQL 语句结尾之后找到字符。”。如图:
试图进行多表查询然后更新有一定的难度,不懂该如何写SQL语句。转载地址:https://blog.csdn.net/zyjq52uys/article/details/88665663 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!