VB.NET学习笔记:ADO.NET操作ACCESS数据库——数据集DataSet数据管理(DataAdapter查询更新数据库)
发布日期:2021-06-29 11:32:12 浏览次数:2 分类:技术文章

本文共 10892 字,大约阅读时间需要 36 分钟。

DataAdapter与数据源提供程序相关,,命名空间为System.Data.OleDb,相应的DataAdapter对象在System.Data.OleDb空间里对应的是OleDbDataAdapter对象。

而DataTable对象和DataSet对象同属于System.Data命名空间,可见其与数据源无关。DataTable对象可作为DataSet对象中的表,也可以单独作为数据集。 体系结构。
ADO.NET 体系结构
使用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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:VB.NET学习笔记:ADO.NET操作ACCESS数据库——OleDbDataAdapter的Update方法更新数据库的秘密(行状态RowState和行版本 DataRowVersion)
下一篇:VB.NET学习笔记:ADO.NET操作ACCESS数据库——在内存中构建数据库(DataSet数据集和DataTable数据表)

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月08日 18时28分20秒