趣味理解ADO.NET对象模型
输水管——DataAdapter
DataAdapter提供连接DataSet对象和数据源的桥梁。DataAdapter使用Command对象在数据源中执行SQL命令,以便将数据加载到DataSet中,并使DataSet中数据的更改与数据源保持一致。
趣味理解 |
DataAdapter就像一根输水管,通过发动机,把水从水源输送到水库里进行保存。 |
1.创建SqlDataAdapter
(1)初始化SqlDataAdapter类的新实例。
string conString = "data source=127.0.0.1;Database=codematic;user id=sa;
password=";
SqlConnection myConnection = new SqlConnection(conString);
SqlCommand cmd = myConnection.CreateCommand();
cmd.CommandText = "SELECT * FROM P_Product";
DataSet ds = new DataSet();
myConnection.Open();
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
adapter.Fill(ds, "ds");
myConnection.Close();
(2)使用指定的 SqlCommand 初始化 SqlDataAdapter 类的新实例。
string conString = "data source=127.0.0.1;Database=codematic;user id=sa;
password=";
SqlConnection myConnection = new SqlConnection(conString);
DataSet ds = new DataSet();
SqlCommand cmd = myConnection.CreateCommand();
cmd.CommandText = "SELECT * FROM P_Product";
myConnection.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(ds, "ds");
myConnection.Close();
(3)使用selectcommand字符串 和 SqlConnection对象初始化SqlDataAdapter 类的新实例。
string conString = "data source=127.0.0.1;Database=codematic;user id=sa;
password=";
string strSQL = "SELECT * FROM P_Product";
SqlConnection myConnection = new SqlConnection(conString);
DataSet ds = new DataSet();
myConnection.Open();
SqlDataAdapter adapter = new SqlDataAdapter(strSQL, myConnection);
adapter.Fill(ds, "ds");
myConnection.Close();
(4)使用selectcommand字符串和一个连接字符串初始化SqlDataAdapter类的新实例。
string conString = "data source=127.0.0.1;Database=codematic;user id=sa;
password=";
string strSQL = "SELECT * FROM P_Product";
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(strSQL, conString);
adapter.Fill(ds, "ds");
2.DataAdapter和SqlConnection、SqlCommand建立关联
方式1:DataAdapter在构造参数时建立。
方式2:通过SelectCommand属性建立。
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(strSQL, myConnection);
5.1.6 输水管——DataReader
通过执行ExecuteReader方法可以返回一个DataReader 对象。DataReader以只进、只读方式返回数据,从而提高应用程序的性能。这样可以节省 DataSet 所使用的内存,并省去创建 DataSet 并填充其内容所需的处理。
趣味理解 |
DataReader 也是一种水管,和DataAdapter不同的是,DataReader不把水输送到水库里面,而是单向地直接把水送到需要水的用户那里或田地里,所以要比在水库中转一下更快。 |
(1)遍历DataReader结果集。
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Response.Write(dr.GetInt32(0).ToString()+ ", "+ dr.GetString(1) + "
");
}
dr.Close();
(2)使用序数索引器。
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Response.Write(dr[0].ToString() + ", " + dr[1].ToString() + "
");
}
dr.Close();
(3)使用列名索引器。
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Response.Write(dr["ProductId"].ToString()+", "+dr["Name"].ToString());
}
dr.Close();
(4)使用类型访问器。
public char GetChar(int i); 获取指定列的单个字符串形式的值
public DateTime GetDateTime(int i); 获取指定列的 DateTime 对象形式的值
public short GetInt16(int i); 获取指定列的 16 位有符号整数形式的值
public string GetString(int i); 获取指定列的字符串形式的值
(5)得到DataReader的列信息。
dr.FieldCount 获取当前行中的列数
dr.GetFieldType(序号) 获取是对象的数据类型的 Type
dr.GetDataTypeName(序号) 获取源数据类型的名称
dr.GetName(序号) 获取指定列的名称
dr.GetOrdinal(序号) 在给定列名称的情况下获取列序号
(6)得到数据表的信息。
DataTable dt=dr.GetSchemaTable();
(7)操作多个结果集。
SqlDataReader dr = cmd.ExecuteReader();
do
{
while (dr.Read())
{
Response.Write(dr.GetInt32(0).ToString()+", "+dr.GetString(1));
}
}
while(myReader.NextResult());//使数据读取器前进到下一个结果集
dr.Close();
下面是一些使用DataReader获得最佳性能的技巧。
l 在使用带参数的Command前,必须关闭DataReader。
l 完成读数据之后一定要关闭DataReader。如果使用Connection只返回DataReader,那么关闭DataReader之后立刻关闭它。另外一个显式关闭Connection的方法是将CommandBehavior.CloseConnection传递给ExecuteReader方法,以确保关闭DataReader时相应的连接也被关闭。如果从一个方法返回DataReader,而且不能控制DataReader的相关连接的关闭,则这样做特别有用。
l 不能在层之间远程访问DataReader。DataReader是为已连接好的数据访问而设计的。
l 当访问列数据时,使用类型化访问器,例如GetString、GetInt32等。这使你不用将GetValue返回的Object强制转换成特定类型。
l 一个单一连接每次只能打开一个DataReader。如果想在相同的数据存储区上同时打开两个DataReader,则必须显式创建两个连接,每个DataReader一个。这是ADO.NET为池化连接的使用提供更多控制的一种方法。
l 在默认情况下,DataReader每次Read时都要将整行加载到内存。这允许在当前行内随机访问列。如果不需要这种随机访问,为了提高性能,则将CommandBehavior.SequentialAccess传递给ExecuteReader调用。这将DataReader的默认行为更改为仅在请求时将数据加载到内存。注意,CommandBehavior. SequentialAccess要求顺序访问返回的列。也就是说,一旦读过返回的列,就不能再读它的值了。
l 如果已经读取了来自DataReader的数据,但仍然有大量挂起的未读结果,则在关闭DataReader之前先要取消Command。因为取消Command可使服务器放弃这些结果,从而释放服务器的资源。
5.1.7 随用随关,释放资源
对于C#程序员来说,确保始终关闭Connection和DataReader对象的一个方便的方法就是使用using语句。using语句在离开自己的作用范围时,会自动调用被“使用”的对象的Dispose。例如:
string connectionString = "data source=127.0.0.1;Database=codematic;
user id=sa;password=";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
SqlCommand cmd = myConnection.CreateCommand();
cmd.CommandText = "SELECT * FROM P_Product";
myConnection.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
Response.Write(dr.GetInt32(0).ToString()+","+dr.GetString(1)+"
");
}
}
}
本文出自《亮剑.NET. .NET深入体验与实战精要》一书