我使用using
:
using (var reader = data.CreateCommand(sql).ExecuteDataReader())
在这种情况下,data
是内部持有SqlConnection
的某些对象。CreateCommand(sql)
功能返回SqlCommand
,ExecuteDataReader
返回SqlDataReader
。由于SqlCommand
和SqlDataReader
都是IDisposable
,因此是否可以通过此使用using
语句来处理它们?
目前我已经这样做了:
using (var cmd = data.CreateCommand(sql))
using (var reader = cmd.ExecuteDataReader())
但是我想知道是否可以按照上述说明?
"如果可以将它们组合在一起" - 两个using
完全很好,因为两者都需要处置。
您可以通过提取方法将它们结合在一起:
void RunWithReader(string sql, Action<SQLDataReader> action)
{
using (var cmd = data.CreateCommand(sql))
using (var reader = cmd.ExecuteDataReader())
action(reader);
}
然后您可以使用lambda
RunWithReader("whatever command", reader =>
{
... // while(reader.Read() { ... } - this could also be extracted
});
同意马修·沃森(Matthew Watson)的评论。您需要两个 usings
statemets。这是带有其他推理的相关问题。sqlConnection sqlcommand sqldatareader idisposable
您显示代码的方式不处理Inner IDisposable
(IDbCommand
)。
您有两个选择:
您可以将其全部放入一个using
中:
using (IDisposable cmd = data.CreateCommand(), reader = ((IDbCommand)cmd).ExecuteReader())
{
// code here
}
但这很麻烦。另一个选项是嵌套using
语句:
using (var cmd = data.CreateCommand())
{
using (var reader = cmd.ExecuteReader())
{
// code here
}
}
除此之外,您还可以有点复杂,并编写一种扩展方法来帮助(某种)为您清理。
public static class Ex
{
public static void Using<T, R>(this T obj, Func<T, R> create, Action<T, R> use) where R : IDisposable
{
using (var d = create(obj))
{
use(obj, d);
}
}
}
然后您可以这样做:
data.Using(d => d.CreateCommand(), (d, c) => c.Using(c2 => c2.ExecuteReader(), (c3, r) =>
{
// code here
}));
,但也许这并不是什么改进。
一般
您应该
Dispose
每个实现IDisposable
的类。
但是,您的问题专门处理一个方案,其中所有资源都是相关的,如果我的理解是正确的,垃圾收集器将自动为您处置这些资源。
Finalize()
方法(" destructors"或" distrizers")
Finalize()
方法确保在 该实例不再由应用程序引用。
与 Dispose()
方法
Dispose()
方法将"释放组件使用的所有资源"。这意味着此代码块(取自MSDN的executereader方法示例)将正确处理其使用的所有组件...
using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand(queryString, connection); SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) { // ... } }
在这种情况下,处理
SqlConnection
时,它将正确 发布组件使用的所有资源。这意味着:
SqlCommand
SqlDataReader
** 注意:这一直是我的理解 ...
对以下代码进行重构:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(queryString, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// ...
}
}
}
}
手动处置每个资源的主要优点将是 为了获得性能增长,因为我们没有处理
Finalize
方法(比使用Dispose()
更昂贵。
但是,这并不意味着您要Dispose()
所有内容,因为在某些情况下,Finalize()
方法是一个更好的选择。
假设我到目前为止仍然处于良好状态,并且我对垃圾收集者行为的理解是有效的。
我会考虑SqlCommand
(此处完整的代码参考),然后也将处置SqlReader
,这意味着您可以摆脱:
using (SqlCommand command = new SqlCommand(queryString, connection))
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// ...
}
}
在您的情况下将转化为:
using (var cmd = data.CreateCommand(sql)) { var reader = cmd.ExecuteDataReader(); // ... }