4.6 DataAdapter
学习目标
掌握DataAdapter的详细使用方法。
DataAdapter用于从数据源检索数据并填充DataSet中的表。DataAdapter还可将对DataSet所做的更改解析回数据源。DataAdapter使用.NET Framework数据提供程序的Connection对象连接到数据源,并使用Command对象从数据源检索数据以及将更改解析回数据源。
本节示例代码参考:/Code/ch04/StudyDataAdapter。
4.6.1 DataAdapter概述
由于DataSet对象本身不具备和数据源沟通的能力,要修改数据并更新回数据源,需要使用DataAdapter对象,即数据适配器对象。
数据适配器对象,类似于“搬运工”。经常和DataSet结合使用。DataAdapter对象完成的是对数据集的填充和对更新的回传任务。对于DataSet来讲,DataAdapter对象就类似于“搬运工”:它把数据从数据库中“搬运”到DataSet中,DataSet中的数据有了改变,又可以把改变“反映”给数据库。DataAdapter对象做这些事情主要靠的是它所包含的4个Command对象:SelectCommand、InsertCommand、UpdateCommand、DeleteCommand。通过使用SqlCommandBuilder cb=new SqlCommandBuilder(sda) 系统还可以自动生成后3个命令对象。
随.NET Framework提供的每个.NET Framework数据提供程序都具有一个DataAdapter对象:适用于OLE DB的.NET Framework数据提供程序包括一个OleDbDataAdapter对象,适用于SQL Server的.NET Framework数据提供程序包括一个SqlDataAdapter对象,适用于ODBC的.NET Framework数据提供程序包括一个OdbcDataAdapter对象,适用于Oracle的.NET Framework数据提供程序包括一个OracleDataAdapter对象。本小节以SQL Server的.NET Framework数据提供程序为例讲解DataAdapter对象的使用方法,其他提供程序中的DataAdapter对象的使用方法和SQL Server的.NET Framework数据提供程序中的SqlDataAdapter对象的用法基本类似。
4.6.2 SqlDataAdapter对象概述
SqlDataAdapter是DataSet和SQL Server之间的桥接器,用于检索和保存数据。SqlDataAdapter通过对数据源使用适当的Transact-SQL语句映射Fill(它可更改DataSet中的数据以匹配数据源中的数据)和Update(它可更改数据源中的数据以匹配DataSet中的数据)来提供这一桥接。更新是逐行进行的。对于每个已插入、修改和删除的行,Update方法会确定已对其执行的更改的类型(Insert、Update或Delete)。根据更改类型,执行Insert、Update或Delete命令将已修改的行传播给数据源。当SqlDataAdapter填充DataSet时,它为返回的数据创建必需的表和列(如果这些表和列尚不存在)。但是,除非MissingSchemaAction属性设置为AddWithKey,否则这个隐式创建的架构中不包括主键信息。也可以使用FillSchema,让SqlDataAdapter创建DataSet的架构,并在用数据填充它之前就将主键信息包括进去。
SqlDataAdapter与SqlConnection和SqlCommand一起使用,以便在连接到SQL Server数据库时提高性能。
如果使用SQL Server存储过程编辑或删除使用DataAdapter的数据,应确保不要在存储过程定义中使用 SET NOCOUNT ON。这将导致返回的受影响行数为零,DataAdapter将其解释为并发冲突。这种情况下将引发 DBConcurrencyException。
SqlDataAdapter还包括SelectCommand、InsertCommand、DeleteCommand、UpdateCommand和TableMappings属性,以便于数据的加载和更新。
4.6.3 创建SqlDataAdapter
SqlDataAdapter类用作ADO.NET对象模型中和数据连接部分和未连接部分之间的桥梁。SqlDataAdapter从数据库中获取数据,并将其存储在DataSet中。SqlDataAdapter也可能取得DataSet中的更新,并将它们提交给数据库。
SqlDataAdapter是为处理脱机数据而设计的,调用其Fill方法填充DataSet时甚至不需要与数据库的活动连接。即如果调用Fill方法时,SqlDataAdapter与数据库的连接不是打开的,SqlDataAdapter将打开数据库连接,查询数据库,提取查询结果,将查询结果填入DataSet,然后自动关闭数据库的连接。而如果是手动打开连接则需要手动关闭连接对象。下面就是一个简单的创建SqlDataAdapter的代码例子。
SqlConnection conn = new SqlConnection(); conn.ConnectionString = @“Server=DUANKEQI;User ID=sa;Password=sa; Initial Catalog=studentDB;Pooling=true;Min Pool Size=5;Max Pool Size=10; Persist Security Info=False;”; SqlDataAdapter sda = new SqlDataAdapter(); string sqlString=“select * from student order by id asc”; sda.SelectCommand = new SqlCommand(sqlString,conn);
可以看出SqlDataAdapter数据适配器对象就是通过该对象内部所封装的4个命令对象(SelectCommand、InsertCommand、DeleteCommand、UpdateCommand)来完成各种操作的。
4.6.4 通过SqlDataAdapter填充DataSet
使用SqlDataAdapter对象填充DataSet就是使用SqlDataAdapter对象所封装的SelectCommand命令对象来获取数据源的数据,然后使用SqlDataAdapter对象的Fill将数据信息以数据表的方式添加到数据集DataSet中以完成各种操作。SqlDataAdapter的Fill方法调用前不需要有活动的SqlConnection对象,SqlDataAdapter会自己打开指定连接中的数据库,获取查询结果后,关闭与数据库的连接。如果已经存在SqlConnection对象,无论是否已经打开,SqlDataAdapter执行完Fill方法后,均会将SqlConnection对象返回到原始状态。
当程序中的多个SqlDataAdapter对象都使用一个SqlConnection对象时,为避免多次打开与关闭SqlConnection对象,应该在调用SqlDataAdapter的Fill方法前调用SqlConnection的Open方法打开数据库的连接,待完成Fill调用后再调用SqlConnection的Close方法关闭数据库的连接。
下面给出一个完整例子代码。
(1)新建ASP.NET网站项目StudyDataAdapter,删除默认Default.aspx页面,添加页面StudyDataAdapter001.aspx。在页面StudyDataAdapter001.aspx的设计窗口添加一个GridView控件作为显示数据信息的容器,然后直接进入StudyDataAdapter001.aspx页面的代码窗口编写Page_Load初始化代码以便使用SqlDataAdapter对象获取数据源信息进而添加到指定数据集,最后绑定数据集中的信息给GridView控件。下面给出完整Page_Load初始化代码。
protected void Page_Load(object sender, EventArgs e) { SqlConnection conn = new SqlConnection(); conn.ConnectionString = @“Server=DUANKEQI;User ID=sa; Password=sa;Initial Catalog=studentDB;Pooling=true;Min Pool Size=5;Max Pool Size=10; Persist Security Info=False;”; SqlDataAdapter sda = new SqlDataAdapter(); sda.SelectCommand = new SqlCommand(“select * from student order by id asc”,conn); DataSet ds = new DataSet(); //使用SqlDataAdapter对象的Fill方法向DataSet数据集中添加信息作 为表stu,//其实这里的stu属于添加到数据集中的表名 sda.Fill(ds,“stu”); GridView1.DataSource = ds.Tables[“stu”]; GridView1.DataBind(); }
(2)然后按Ctrl+F5组合键,运行显示效果如图4-32所示。
4.6.5 通过SqlDataAdapter更新数据库信息
使用SqlDataAdapter对象更新数据库信息主要就是使用SqlDataAdapter对象所封装的InsertCommand、UpdateCommand、DeleteCommand这3个命令对象来完成的。
接下来举例说明SqlDataAdapter对象如何完成内存表信息更新来更新数据库,会涉及对内存表的一些增加、修改、删除操作等。
(1)在ASP.NET网站项目StudyDataAdapter中添加页面StudyData-Adapter002.aspx。在页面StudyDataAdapter002.aspx的设计窗口添加两个GridView控件作为显示数据信息的容器,页面布局如图4-33所示,页面的HTML源代码如下。
<form id=“form1”runat=“server”> <div id="div001" style="width: 200px; float:left;"> 原始数据表<br /> <asp:GridView ID="GridView1" runat="server"> </asp:GridView> </div> <div id="div002" style="width: 200px; float:left;"> 更新后<br /> <asp:GridView ID="GridView2" runat="server"> </asp:GridView> </div> </form>
(2)从图4-33直接进入StudyDataAdapter002.aspx页面的代码窗口编写Page_Load初始化代码以便使用SqlDataAdapter对象获取数据源信息进而添加到指定数据集,最后绑定数据集中的信息给GridView控件,再完成DataSet中的维护操作(如添加、修改、删除)。下面给出完整Page_Load代码。
protected void Page_Load(object sender, EventArgs e) { SqlConnection conn = new SqlConnection(); conn.ConnectionString = @"Server=DUANKEQI;User ID=sa; Password=sa;Initial Catalog=studentDB;Pooling=true;Min Pool Size=5;Max PoolSize=10; Persist Security Info=False;"; SqlDataAdapter sda = new SqlDataAdapter(); sda.SelectCommand = new SqlCommand("select * from student order by id asc", conn); DataSet ds = new DataSet(); //使用SqlDataAdapter对象的Fill方法向DataSet数据集中添加信息作为 表stu,其实这里的stu属于添加到数据集中的表名 sda.Fill(ds, "stu"); GridView1.DataSource = ds.Tables["stu"]; GridView1.DataBind(); //下面在内存中对datatable进行操作 ////增加新行 //DataRow dr = ds.Tables["stu"].NewRow(); //dr["name"] = "zhangsan"; //dr["sex"] = "男"; //dr["city"] = "西安"; //ds.Tables["stu"].Rows.Add(dr); ////更新1行 //dr = ds.Tables["student"].Rows[0]; //dr["name"] = "张三风"; ////删除2行 //ds.Tables["student"].Rows[1].Delete(); //删除name='zhangsan' for (int i = 0; i < ds.Tables["stu"].Rows.Count; i++) { DataRow dr = ds.Tables["stu"].Rows[i]; if (dr["name"].ToString() == "zhangsan") { ds.Tables["stu"].Rows[i].Delete(); } } //真正把内存中的表的数据变化更新到数据库 //使用SqlCommandBuilder对象以便让系统自动生成对应维护的Insert、 Update 、Delete操作的3个命令对象 SqlCommandBuilder scb = new SqlCommandBuilder(sda); //调用SqlDataAdapter对象的Update方法以执行生成的3个命令对象 sda.Update(ds,"stu"); GridView2.DataSource = ds.Tables["stu"]; GridView2.DataBind(); }
(3)然后按Ctrl+F5组合键,运行显示效果如图4-34所示。
(4)通过图4-34的结果明显可以看出,数据库中的信息已经借助于SqlDataAdapter对象完成了,而且操作也比较简单,核心就是两条语句:“SqlCommandBuilder scb = new SqlCommandBuilder(sda);”使用SqlCommandBuilder对象以便让系统自动生成对应维护的Insert、Update、Delete”操作的3个命令对象Insert、Command、UpdateCommand、DeleteCommand;“sda.Update(ds,“stu”);”调用SqlDataAdapter对象的Update方法以执行生成的3个命令对象,从而更新源数据库。