ado.net数据接口下

来源:互联网 发布:淘宝关键词排名不稳定 编辑:程序博客网 时间:2024/05/22 14:07

篇提到 一个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()方法。


[vb] view plain copy print?
  1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  2.        Dim cn As New SqlConnection("Data Source=(local);Initial Catalog=Sales;Integrated Security=False;User ID=sa;Password=123456;")  
  3.        Dim da As New SqlDataAdapter("select * from grade", cn) '搬运工拉好水  
  4.        Dim ds As New DataSet()  '本地内存准备好容器来装水  
  5.        da.Fill(ds, "mytable")   '装水  
  6.        Dim drow As DataRow          '定义行变量  
  7.        ds.Tables("mytable").PrimaryKey = New DataColumn() {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.            Dim cmdb As New SqlCommandBuilder(da)  '和数据库打个电话,本地内存有水要运过去  
  16.            da.Update(ds, "mytable")               '上面电话里已经说好了,现在把水运到数据库去  
  17.            DataGridView1.DataSource = ds.Tables("mytable"'绑定到控件上显示当前结果  
  18.        Catch ex As Exception  
  19.            MessageBox.Show(ex.ToString)  
  20.        End Try  
  21.   
  22.    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,


[vb] view plain copy print?
  1. Imports System.Data.SqlClient  
  2. Public Class Form1  
  3.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  4.         Dim cn As New SqlConnection("Data Source=.;Initial Catalog=Sales;Integrated Security=False;User ID=sa;Password=123456;")  
  5.         Dim cmd As New SqlCommand("select * from grade", cn)  
  6.         Dim da As New SqlDataAdapter  
  7.         da.SelectCommand = cmd  
  8.         cn.Open()  
  9.         Dim ds As New DataSet  
  10.         da.Fill(ds, "grade")  
  11.         DataGridView1.DataSource = ds.Tables("grade")  
  12.     End Sub  
  13. 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在第二个之前,必须存在。

[vb] view plain copy print?
  1. Imports System.Data.SqlClient  
  2. Public Class Form1  
  3.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  4.         Dim cn As New SqlConnection("Data Source=.;Initial Catalog=Sales;Integrated Security=False;User ID=sa;Password=123456;")  
  5.         Dim Insertcmd As New SqlCommand("insert into grade(学号,姓名,数学) values(111,'盖茨',59)", cn)  
  6.         Dim Selectcmd As New SqlCommand("select * from grade where 学号=111", cn)  
  7.         Dim Updatecmd As New SqlCommand("update grade set 数学=60 where 学号=111", cn)  
  8.         Dim da As New SqlDataAdapter  
  9.         da.SelectCommand = Selectcmd  
  10.         da.UpdateCommand = Updatecmd  
  11.         da.InsertCommand = Insertcmd  
  12.         Dim ds As New DataSet  
  13.         da.Fill(ds, "grade1")  
  14.         cn.Open()  
  15.         da.InsertCommand.ExecuteNonQuery()  
  16.         da.Fill(ds, "grade2")  
  17.         da.UpdateCommand.ExecuteNonQuery()  
  18.         da.Fill(ds, "grade3")  
  19.         DataGridView1.DataSource = ds.Tables("grade1")  
  20.         DataGridView2.DataSource = ds.Tables("grade2")  
  21.         DataGridView3.DataSource = ds.Tables("grade3")  
  22.     End Sub  
  23. 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是用户手中的“数据库”,可以任意来操作它,其表名也是可以自己定义的,同时它还可以再次返回到原来服务器上的数据库 中。


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

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

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

 

[vb] view plain copy print?
  1. Public Class Form1  
  2.   
  3.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  4.         Dim ds As New DataSet  '建立水缸  
  5.         Dim dt As New DataTable("Squ")  '建立水缸中的分格容器即表,表名:Squ  
  6.         Dim drow As DataRow            '不能new,因为分格容器中含一个列和一个行对象  
  7.         dt.Columns.Add(New DataColumn("数字"GetType(Integer)))  '添加一列  
  8.         dt.Columns.Add(New DataColumn("平方"GetType(Integer)))  
  9.         Dim i As Integer  
  10.         For i = 3 To 10  
  11.             drow = dt.NewRow       '表中新增空行,下面赋值  
  12.             drow("数字") = i '或drow(0)  
  13.             drow(1) = i * i  
  14.             dt.Rows.Add(drow)      '新行进入表中  
  15.         Next  
  16.         ds.Tables.Add(dt)         '把这个已经有“内容”的表,填充到水缸中  
  17.         DataGridView1.DataSource = ds.Tables("Squ")  
  18.   
  19.     End Sub  
  20. End Class  

                

                          


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

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

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

                        



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


                   在DataSet的DataTable上建立DataView。

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

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

                   下例是一个查找


[vb] view plain copy print?
  1. Imports System.Data.SqlClient  
  2. Public Class Form1  
  3.   
  4.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  5.         Dim cn As New SqlConnection("Data Source=.;Initial Catalog=Sales;Integrated Security=False;uid=sa;Password=123456;")  
  6.         Dim cmd As New SqlCommand("select * from grade", cn)  
  7.         Dim da As New SqlDataAdapter  
  8.         da.SelectCommand = cmd  
  9.         Dim ds As New DataSet  
  10.         da.Fill(ds, "grade")  
  11.         Dim dv As New DataView(ds.Tables("grade"))  
  12.         dv.RowFilter = "数学>60"  
  13.         dv.Sort = "数学 desc,英语"  
  14.         DataGridView1.DataSource = dv  
  15.         cn.Close()  
  16.     End Sub  
  17. 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等进行合并等


[vb] view plain copy print?
  1. Imports System.Data.SqlClient  
  2. Public Class Form1  
  3.   
  4.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  5.         Dim cn As New SqlConnection("Data Source=.;Initial Catalog=Sales;Integrated Security=False;uid=sa;Password=123456;")  
  6.         Dim cmd As New SqlCommand("select * from grade", cn)  
  7.         Dim da As New SqlDataAdapter  
  8.         da.SelectCommand = cmd  
  9.         Dim ds As New DataSet  
  10.         da.Fill(ds, "grade")  
  11.         Dim dv As New DataView(ds.Tables("grade"), """姓名", DataViewRowState.CurrentRows) '指定默认查找列为姓名  
  12.         Dim rowIndex As Integer = dv.Find(TextBox1.Text)  
  13.         If rowIndex = -1 Then  
  14.             Label1.Text = "没相关记录"  
  15.         Else  
  16.             Label1.Text = dv(rowIndex)("姓名").ToString & " " & dv(rowIndex)("语文").ToString & " " & dv(rowIndex)("数学").ToString  
  17.         End If  
  18.         cn.Close()  
  19.     End Sub  
  20. End Class  

                        



                   5个关键对象已经完毕。

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

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

0 0