![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
using(SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_SELECT_ITEMS_BY_PRODUCT, parm))
{
// Scroll through the results
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (rdr.Read())
{
ItemInfo item = new ItemInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetInt32(2), rdr.GetDecimal(3), rdr.GetString(4), rdr.GetString(5), rdr.GetString(6), rdr.GetString(7));
//Add each item to the arraylist
itemsByProduct.Add(item);
}
}
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
{
SqlCommand cmd = new SqlCommand();
SqlConnection conn = new SqlConnection(connectionString);
![](/Images/OutliningIndicators/InBlock.gif)
// we use a try/catch here because if the method throws an exception we want to
// close the connection throw code, because no datareader will exist, hence the
// commandBehaviour.CloseConnection will not work
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
try
{
PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
return rdr;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
catch
{
conn.Close();
throw;
}
}
首先在using语句中初始化一个对象,并将其引用保存在一个变量中.然后在和using语句匹配的大括号内访问该变量.编译这段代码时,编译器会自动产生一个try块和一个finally块.在finally块中,编译器会产生代码将变量转型为一个IDisposable接口,并调用该接口上的Dispose方法.很明显,using语句只能用于那些实现了IDisposable接口的类型.
前面代码在using语句中初始化了一个SqlDataReader对象,该对象由ExecuteReader()方法返回得到,该方法中有这么一句
CommandBehavior.CloseConnection,在没有异常的情况下并不会关闭conn,但是当using语句执行完之后,会自动调用SqlDataReader的Dispose()方法在该方法中会关闭SqlDataReader,当SqlDataReader关闭的时候,由于
CommandBehavior.CloseConnection,相应的conn也会关闭,不会造成资源的浪费.