c#using带有双IDisposable的语句

时间:2017-02-23 09:31:08

标签: c# using idisposable

我使用using发表以下声明:

using (var reader = data.CreateCommand(sql).ExecuteDataReader())

在这种情况下data是一个内部持有SqlConnection的对象。 CreateCommand(sql)函数返回SqlCommandExecuteDataReader返回SqlDataReader。由于SqlCommandSqlDataReader都是IDisposable,它们是否都会被using语句使用?

现在我这样做了:

using (var cmd = data.CreateCommand(sql))
using (var reader = cmd.ExecuteDataReader())

但我想知道是否可以将它们组合起来如上所述?

3 个答案:

答案 0 :(得分:3)

同意Matthew Watson的评论。您需要同时拥有两个End Sub 州。 以下是相关问题和其他推理。 SqlConnection SqlCommand SqlDataReader IDisposable

答案 1 :(得分:3)

“如果可以将它们组合起来” - 两个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
});

答案 2 :(得分:1)

您展示代码的方式内部IDisposableIDbCommand)未被处理。

您有两种选择:

你可以把它全部放在一个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
}));

但也许这并没有太大改善。