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()方法。


 Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        Dim cn As New SqlConnection("Data Source=(local);Initial Catalog=Sales;Integrated Security=False;User ID=sa;Password=123456;")
        Dim da As New SqlDataAdapter("select * from grade",cn) '搬运工拉好水
        Dim ds As New DataSet()  '本地内存准备好容器来装水
        da.Fill(ds,"mytable")   '装水
        Dim drow As DataRow          '定义行变量
        ds.Tables("mytable").PrimaryKey = New DataColumn() {ds.Tables("mytable").Columns("学号")} '设置内存表中的主键
        drow = ds.Tables("mytable").Rows.Find(TextBox1.Text) '根据学号定准到对应行
        Try
            drow("学号") = TextBox1.Text     '对应行赋值
            drow("姓名") = TextBox2.Text
            drow("语文") = TextBox3.Text
            drow("数学") = TextBox4.Text
            drow("英语") = TextBox5.Text
            Dim cmdb As New SqlCommandBuilder(da)  '和数据库打个电话,本地内存有水要运过去
            da.Update(ds,"mytable")               '上面电话里已经说好了,现在把水运到数据库去
            DataGridView1.DataSource = ds.Tables("mytable") '绑定到控件上显示当前结果
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try

    End Sub

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

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



4.4 DataAdapter的Command属性

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

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

如果是查询则是SelectCommand

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

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


Imports System.Data.SqlClient
Public Class Form1
    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        Dim cn As New SqlConnection("Data Source=.;Initial Catalog=Sales;Integrated Security=False;User ID=sa;Password=123456;")
        Dim cmd As New SqlCommand("select * from grade",cn)
        Dim da As New SqlDataAdapter
        da.SelectCommand = cmd
        cn.Open()
        Dim ds As New DataSet
        da.Fill(ds,"grade")
        DataGridView1.DataSource = ds.Tables("grade")
    End Sub
End Class


注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在第二个之前,必须存在。

Imports System.Data.SqlClient
Public Class Form1
    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        Dim cn As New SqlConnection("Data Source=.;Initial Catalog=Sales;Integrated Security=False;User ID=sa;Password=123456;")
        Dim Insertcmd As New SqlCommand("insert into grade(学号,姓名,数学) values(111,'盖茨',59)",cn)
        Dim Selectcmd As New SqlCommand("select * from grade where 学号=111",cn)
        Dim Updatecmd As New SqlCommand("update grade set 数学=60 where 学号=111",cn)
        Dim da As New SqlDataAdapter
        da.SelectCommand = Selectcmd
        da.UpdateCommand = Updatecmd
        da.InsertCommand = Insertcmd
        Dim ds As New DataSet
        da.Fill(ds,"grade1")
        cn.Open()
        da.InsertCommand.ExecuteNonQuery()
        da.Fill(ds,"grade2")
        da.UpdateCommand.ExecuteNonQuery()
        da.Fill(ds,"grade3")
        DataGridView1.DataSource = ds.Tables("grade1")
        DataGridView2.DataSource = ds.Tables("grade2")
        DataGridView3.DataSource = ds.Tables("grade3")
    End Sub
End Class


品味里面的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是用户手中的“数据库”,可以任意来操作它,其表名也是可以自己定义的,同时它还可以再次返回到原来服务器上的数据库 中。


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

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

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

Public Class Form1

    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        Dim ds As New DataSet  '建立水缸
        Dim dt As New DataTable("Squ")  '建立水缸中的分格容器即表,表名:Squ
        Dim drow As DataRow            '不能new,因为分格容器中含一个列和一个行对象
        dt.Columns.Add(New DataColumn("数字",GetType(Integer)))  '添加一列
        dt.Columns.Add(New DataColumn("平方",GetType(Integer)))
        Dim i As Integer
        For i = 3 To 10
            drow = dt.NewRow       '表中新增空行,下面赋值
            drow("数字") = i '或drow(0)
            drow(1) = i * i
            dt.Rows.Add(drow)      '新行进入表中
        Next
        ds.Tables.Add(dt)         '把这个已经有“内容”的表,填充到水缸中
        DataGridView1.DataSource = ds.Tables("Squ")

    End Sub
End Class


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

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

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



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


在DataSet的DataTable上建立DataView。

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

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

下例是一个查找


Imports System.Data.SqlClient
Public Class Form1

    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        Dim cn As New SqlConnection("Data Source=.;Initial Catalog=Sales;Integrated Security=False;uid=sa;Password=123456;")
        Dim cmd As New SqlCommand("select * from grade",cn)
        Dim da As New SqlDataAdapter
        da.SelectCommand = cmd
        Dim ds As New DataSet
        da.Fill(ds,"grade")
        Dim dv As New DataView(ds.Tables("grade"))
        dv.RowFilter = "数学>60"
        dv.Sort = "数学 desc,英语"
        DataGridView1.DataSource = dv
        cn.Close()
    End Sub
End Class


过滤条件由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等进行合并等


Imports System.Data.SqlClient
Public Class Form1

    Private Sub Button1_Click(sender As Object,"grade")
        Dim dv As New DataView(ds.Tables("grade"),"","姓名",DataViewRowState.CurrentRows) '指定默认查找列为姓名
        Dim rowIndex As Integer = dv.Find(TextBox1.Text)
        If rowIndex = -1 Then
            Label1.Text = "没相关记录"
        Else
            Label1.Text = dv(rowIndex)("姓名").ToString & " " & dv(rowIndex)("语文").ToString & " " & dv(rowIndex)("数学").ToString
        End If
        cn.Close()
    End Sub
End Class



5个关键对象已经完毕。

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
  Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
  PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
  沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")