Ado.Net: 关闭 SqlCommand 是否会导致关闭 DataReader
Ado.Net: Does closing SqlCommand cause closing DataReader
今天我查看了一些遗留代码,我开始担心了。需要明确关闭 DataReader
。
我的问题是:关闭 SqlCommand
是否也会关闭关联的 DataReader
?
这是我的代码:
using (var conn = new SqlConnection(this.ConnectionString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "House_GetHouseById";
SqlCommandBuilder.DeriveParameters(cmd);
cmd.Parameters["@HouseId"].Value = houseId;
var reader = cmd.ExecuteReader())
while (reader.Read())
{
}
}
}
在这段来自 msdn 命令的片段中没有明确关闭:
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
// Call Close when done reading.
reader.Close();
}
没有。 SqlCommand.Dispose
本质上是一个空操作¹,它不会关闭您的 SqlDataReader
。
从技术上讲,关闭 SqlConnection
应该会关闭所有资源,有关详细信息,请参阅此问题:
- Is closing/disposing an SqlDataReader needed if you are already closing the SqlConnection?
但是,这是不好的做法 -- 您依赖于 SqlClient 库的实现细节。 "correct" 方法是处理(通过 Dispose
或 using
)所有 IDisposable
的东西。因此,你的代码应该这样写:
using (var conn = new SqlConnection(this.ConnectionString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "House_GetHouseById";
SqlCommandBuilder.DeriveParameters(cmd);
cmd.Parameters["@HouseId"].Value = houseId;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do something
}
}
}
}
¹ 注意,OleDbCommand
和 SqlCeCommand
等其他库的命令 类 并非如此,所以不要养成不配置命令的习惯。
您总是可以将数据读取器包装在 using 指令中,以便在执行超出范围时立即关闭命令,就像 sqlcommand
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader != null)
{
while (reader.Read())
{
//do something
}
}
} // reader is closed here
reader.Close(); //is another way but its too easy to be forgotten.
今天我查看了一些遗留代码,我开始担心了。需要明确关闭 DataReader
。
我的问题是:关闭 SqlCommand
是否也会关闭关联的 DataReader
?
这是我的代码:
using (var conn = new SqlConnection(this.ConnectionString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "House_GetHouseById";
SqlCommandBuilder.DeriveParameters(cmd);
cmd.Parameters["@HouseId"].Value = houseId;
var reader = cmd.ExecuteReader())
while (reader.Read())
{
}
}
}
在这段来自 msdn 命令的片段中没有明确关闭:
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
// Call Close when done reading.
reader.Close();
}
没有。 SqlCommand.Dispose
本质上是一个空操作¹,它不会关闭您的 SqlDataReader
。
从技术上讲,关闭 SqlConnection
应该会关闭所有资源,有关详细信息,请参阅此问题:
- Is closing/disposing an SqlDataReader needed if you are already closing the SqlConnection?
但是,这是不好的做法 -- 您依赖于 SqlClient 库的实现细节。 "correct" 方法是处理(通过 Dispose
或 using
)所有 IDisposable
的东西。因此,你的代码应该这样写:
using (var conn = new SqlConnection(this.ConnectionString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "House_GetHouseById";
SqlCommandBuilder.DeriveParameters(cmd);
cmd.Parameters["@HouseId"].Value = houseId;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do something
}
}
}
}
¹ 注意,OleDbCommand
和 SqlCeCommand
等其他库的命令 类 并非如此,所以不要养成不配置命令的习惯。
您总是可以将数据读取器包装在 using 指令中,以便在执行超出范围时立即关闭命令,就像 sqlcommand
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader != null)
{
while (reader.Read())
{
//do something
}
}
} // reader is closed here
reader.Close(); //is another way but its too easy to be forgotten.