ADO.NET的记忆碎片(三)
接着ADO.NET的记忆碎片(二)继续
DataAdapter类
主要是在数据源以及DataSet 之间执行数据传输的工作,它可以透过Command 对象下达命令后,并将取得的数据放入DataSet 对象中。这个对象是架构在Command对象上,并提供了许多配合DataSet 使用的功能。
构造一个DataAdapter对象有三方法: www.zzzyk.com
string strConn ="...";//连接字符串
string strSql = "select * from MytableName1";
SqlConnection cn = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand(strSql,cn);
1、SqlDataAdapter da1 = new SqlDataAdapter(strSql,strConn);
2、SqlDataAdapter da2 = new SqlDataAdapter(strSql,cn);
3、SqlDataAdapter da3 = new SqlDataAdapter(cmd);
其实这三种方法很多时候可以互换使用,不过第一种有一些美中不足,当需要多次实例化的时候,并且这个strConn链接字符串也是一样的时候,会带来一个小问题,假设DataAdapter实例化了N次,那么也会实例化N个不同Connection的链接,其实我们只要一个这样的Connection的链接就好了,明显这是没有必要的性能损耗,2、3这两种方法可以显示的指定Connection实例,可以避免这样的问题。
看看构造好了的SqlDataAdapter怎样将查询的结果存储在DataSet实例中呢,可是使用Fill()方法:
DataSet ds = new DataSet();
da.Fill(ds);
foreach(DataRow row in ds.Tables[0].Rows)
{
Console.WriteLine("{0}--{1}",row[0],row["CustomerName"]);
}
关于Fill()方法的一个小说明:其实当程序进入Fill()方法后,会先检查Connection是否打开,要是打开,就可以继续数据的处理,最后推出Fill()方法;要是没有打开,就会先打开Connection链接,然后处理数据,在退出方法之前,关闭Connection链接,在Fill()方法的前后Connection状态是没有改变的,Fill()的聚合性很强的,用起来很简单。看看下面的代码:
cn.Close();
DataSet ds1 = new DataSet();
DataSet ds2 = new DataSet();
da.Fill(ds1);
da.Fill(ds2);
可以看到Connection是关闭着的,不过Fill()还是很好的完成了数据的处理,但是我们知道,其实上面的代码性能是可以进一步提升的,因为在调用Fill()方法两次中,对Connection实例进行了:Open();Close();Open();Close();的两次调用,可以把代码改进:
cn.Close();
DataSet ds1 = new DataSet();
DataSet ds2 = new DataSet();
cn.Open();
da.Fill(ds1);
da.Fill(ds2);
cn.Close();
我们看看存储在DataSet中的DataTable的名称是什么:
Console.WriteLine("{0}",ds.Tables[0].TableName);
会看到是“Table”。这个结果并不能让我们兴奋,为什么是这个名称?因为,SqlDataAdapter在背后是隐式创建了一个SqlDataReader,以获得查询的结果。在SqlDataAdapter查第一行数据之前,它会收集SqlDataReader的架构的信息,已确定列名称和类型,但是在默认的情况下,查询引用的表名称不能通过SqlDataReader来获得。所以在SqlDataReader中就会赋予了“Table”作为查询结果的表名称,最后导致了上面的这个结果。我们可以使用TableMappings这个属性改变这个纠结的现象:
DataSet ds = new DataSet();
da.TableMappings.Add("Table","MyTableName");
da.Fill(ds);
Console.WriteLine("{0}",ds.Tables[0].TableName);//会输出MyTableName
Add()方法中两个参数,第一个参数是表示数据库中的表名称,第二个参数是表示DataSet中的表名称。因为SqlDataReader不能获得真的表名,所以赋予了“Table”作为查询结果的表名称,为了性能更好,这也是没有办法的事情。
Fill()方法的重载:
DataSet ds = new DataSet();
DataTable table = new DataTable();
1、da.Fill(ds);
2、da.Fill(ds,"MyTableName");//表示存储在DataSet中的表名称是MyTableName,是da.TableMappings.Add("Table","MyTableName");da.Fill(ds);的语法唐
3、da.Fill(table);
希望将查询的结果映到自己设置的DataSet里,使用TableMappings和ColumnMappings的设置完成自己想要的:
DataTableMapping tableMap;
tableMap=da.TableMappings.Add("Table","MyTableName");
tableMap.ColumnMappings.Add("EmpID","MyEmpID");
tableMap.ColumnMappings.Add("EmpName","MyEmpName");
Add()方法中两个参数,第一个参数是表示数据库中的表名称,第二个参数是表示DataSet中的表名称。SqlDataReader可以获得列名称和类型,不过不能获得表名称。然后只要执行Fill()方法,就可以在DataSet中看到查询的结果并且是自己设置的表名和列名:
da.Fill(ds);
Console.WriteLine("{0}",ds.Tables[0].TableName);
foreach(DataColumn col in ds.Tables[0].Columns)
{
Console.WriteLine("{0}",col.Name);
}
使用批量查询
有时候我们在一次查询中返回多个表结果:
string strConn ="...";//连接字符串
string strSql = "select * from MytableName1;"+"select * from MytableName2";
SqlDataAdapter da = new SqlDataAdapter(strSql,strConn);
da.TableMappings.Add("Table","MyTableName1");
da.TableMappings.Add("Table1","MyTableName2");
DataSet ds = new DataSet();
da.Fill(ds);
foreach(DataTable table in ds.Tables)
{
Console.WriteLine("{0}",table.TableName);
}
从中可以看出来MyTableName1、MyTableName1是我们为结果中的两个表命名,而Table和Table1是SqlDataReader不能获得数据库的表名,自己给添加的。最后说一句,DataAdapter背后是隐式的创建了DataReader来获取结果集的。
摘自 八神吻你
补充:Web开发 , ASP.Net ,