ADO.NET系列之DataAdapter对象
我们前两篇文章介绍了ADO.NET的概念,以及介绍了Connection和Command对象,基本的增删改查操作都能够实现了,本节再介绍一个强大的DataAdapter对象。
我们先来看看DataAdapter对象的工作原理如下图所示:
DataAdapter首先将构造一个SelectCommand实例(本质就一个Command对象),然后检查是否打开连接,如果没有打开连接则打开连接,紧接着调用DataReader接口检索数据,最后根据维护的映射关系,将检索到得数据库填充到本地的DataSet或者DataTable中。同理,我们需要更新数据源时,DataAdatper则将本地修改的数据,跟据映射关系,构造InsertCommand,UpdateCommnad,DeleteCommand对象,然后执行相应的命令。
为什么说DataAdapter对象强大呢?首先DataAdapter对象可以执行查询操作,严格意义上也不是执行,而是可以填充DataSet,DataTable对象,再一个DataAdapter对象可以进行批量更新和批量删除,至于批量添加我们有SqlBulkCopy对象,后面文章会介绍SqlBulkCopy对象。
DataAdapter.Net提供了四种Connection 对象:
- 针对Sql Server的SqlDataAdapter,位于命名空间System.Data.SqlClient下
- 针对Oledb链接的OledbDataAdapter,位于命名空间System.Data.Oledb下
- 针对MySql的MySqlDataAdapter,位于命名空间System.Data.MySqlClient下(需要引用MySql.Data.dll)
- 针对Oracle的OracleDataAdapter,位于命名空间Oracle.ManagedDataAccess.Client(需引用Oracle.ManagedDataAccess.dll)
我们先来看看DataAdapter对象填充DataSet,DataTable对象的示例:
string connectionString = "Data Source=.;Initial Catalog=ax_log;User Id=sa;Password=sa123;"; using (SqlConnection con = new SqlConnection(connectionString)) { string sql = "select * from eftest where id=@id"; SqlParameter para = new SqlParameter("@id", 1); using (SqlCommand com = new SqlCommand(sql, con)) { DataSet ds = new DataSet(); try { com.Parameters.Add(para); con.Open(); SqlDataAdapter adapter = new SqlDataAdapter(com); adapter.Fill(ds); foreach (DataRow s in ds.Tables[0].Rows) { Console.WriteLine("ID:"+s["id"].ToString()); Console.WriteLine("Name:" + s["name"].ToString()); } } catch (Exception ex) { } } }
DataAdapter对象实现批量修改
string connectionString = "Data Source=.;Initial Catalog=ax_log;User Id=sa;Password=sa123;"; using (SqlConnection con = new SqlConnection(connectionString)) { string sql = "select * from eftest "; DataSet ds = new DataSet(); try { con.Open(); SqlDataAdapter adapter = new SqlDataAdapter(sql, con); adapter.Fill(ds);//填充ds for (int k = 0; k < ds.Tables[0].Rows.Count; k++) { Console.WriteLine(ds.Tables[0].Rows[k].RowState);//RowState:Unchanged Console.WriteLine(ds.Tables[0].Rows[k][1]); ds.Tables[0].Rows[k][1] = "abc";//每一行的第二列都修改为abc Console.WriteLine(ds.Tables[0].Rows[k][1]); Console.WriteLine(ds.Tables[0].Rows[k].RowState);//RowState:Modified } SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(adapter);//这行不能缺少,除非自定义Command赋值给adapter.UpdateCommand Console.WriteLine("生成的Update语句:{0}", cmdBuilder.GetUpdateCommand().CommandText); adapter.Update(ds);//更新到数据源中 ds.AcceptChanges();//提交到DataTable中 提交后DataRow.RowState会修改为Unchanged } catch (Exception ex) { Console.WriteLine(ex.Message); } }
根据上代码,我们先要介绍下DataRow.RowState属性,DataRowState是一个枚举类型:
// // 摘要: // 该行已被创建,但不属于任何 System.Data.DataRowCollection。System.Data.DataRow 在以下情况下立即处于此状态:创建之后添加到集合中之前;或从集合中移除之后。 Detached = 1, // // 摘要: // 该行自上次调用 System.Data.DataRow.AcceptChanges 以来尚未更改。 Unchanged = 2, // // 摘要: // 该行已添加到 System.Data.DataRowCollection 中,System.Data.DataRow.AcceptChanges 尚未调用。 Added = 4, // // 摘要: // 该行已通过 System.Data.DataRow 的 System.Data.DataRow.Delete 方法被删除。 Deleted = 8, // // 摘要: // 该行已被修改,System.Data.DataRow.AcceptChanges 尚未调用。 Modified = 16
我们可以根据RowState属性可以很清楚的知道DataTable中的每一行数据是新增的?修改过?删除了?还是未曾改变! 其实adapter.Update(ds)更新数据也是根据这个属性批量向数据源更新的。
DataAdapter实现批量添加和批量删除都是大同小异,只是操作DataTable添加或者删除就行了。