2

我正在尝试习惯在 C# 中使用“使用”块,但我很难理解何时应该使用它们。

这是一个例子。

我的原始代码,没有using块:

SqlConnection conn = new SqlConnection(cCon.getConn());
    SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", xxx));
    cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
    try
    {
        conn.Open();
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    { }
    finally
    {
        conn.Close();
    }

但我真的应该这样做吗?还是我应该使用(SqlConnection conn = new SqlConnection(cCon.getConn()))?请帮助我理解这一点。我原来做的方式错了吗?

SqlConnection conn = new SqlConnection(cCon.getConn());
   using( SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", xxx));
    cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
    try
    {
        conn.Open();
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    { }
    finally
    {
        conn.Close();
    }
}
4

5 回答 5

10

但我很难理解什么时候应该使用它们。

这很简单。每次处理实现 IDisposable 接口的类时,都应该使用它们。像这样:

using (SqlConnection conn = new SqlConnection(cCon.getConn()))
using (SqlCommand cmd = conn.CreateCommand())
{
    conn.Open();
    cmd.CommandText = "sp_SaveSomething";
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", xxx));
    cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
    cmd.ExecuteNonQuery();
}

如果你想处理一些异常,你可以将你想处理的代码包装在 try/catch 语句中:

try
{
    using (SqlConnection conn = new SqlConnection(cCon.getConn()))
    using (SqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "sp_SaveSomething";
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@x", xxx));
        cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
        cmd.ExecuteNonQuery();
    }
}
catch (Exception ex)
{
    // do something here with the exception, don't just consume it,
    // otherwise it's meaningless to catch it
}

正如您所看到的,所有 IDisposable 资源(此代码片段中的 SqlConnection 和 SqlCommand)现在都正确包装在using 语句中,从而保证即使抛出异常也能正确处理它们。因此,您不再需要使用 finally 语句并明确地执行此操作。

还要记住,ADO.NET 使用的connection pool含义是,当您.Open()在 SqlConnection 上调用方法时,您不会打开与数据库的物理连接。您只是从池中抽出一个。当您调用 .Close(或 .Dispose)方法时,您并没有关闭连接。您只是将它返回到连接池,以便它可以被重用。

于 2013-03-26T14:15:19.933 回答
0

如果将其放入 using 块中,则不必关闭连接。Using 块用于实现 IDisposable 的对象。IDisposable 允许对象在被 GC 收集之前清除非托管资源。这释放了内存并允许 GC 收集该对象。

于 2013-03-26T14:16:15.807 回答
0

using 块只是一个 try/finally 子句,具有自动关闭和处置一次性对象的功能。仅当您计划以某种方式处理抛出的异常时,才添加内部 try/catch。在您的示例中,您在 catch 块中什么都不做,因此没有必要。

SqlCommand 和 SqlConnection 都是一次性的,因此您的代码应更改为

using(SqlConnection conn = new SqlConnection(cCon.getConn())
using( SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", xxx));
    cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
    conn.Open();
    cmd.ExecuteNonQuery();
}
于 2013-03-26T14:16:26.657 回答
0

实际上,您应该在这里有几个 using 块,因为SqlConnection两者SqlCommand都实现了IDisposable. 并且using还负责在最后关闭连接,因此显式conn.Close();变得不必要。

    using (SqlConnection conn = new SqlConnection(cCon.getConn()))
    using (SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@x", xxx));
        cmd.Parameters.Add(new SqlParameter("@ORG", ORG));
        try
        {
            conn.Open();
            cmd.ExecuteNonQuery();
        }
        catch (Exception ex)
        {
            // Log error, etc.
        }
    }
于 2013-03-26T14:16:46.607 回答
0

它会这样:

using (SqlConnection conn = new SqlConnection(cCon.getConn()))
{
    using (SqlCommand cmd = new SqlCommand("sp_SaveSomething", conn))
    {
        conn.Open();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@x", xxx));
        cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        

        cmd.ExecuteNonQuery();
    }
}

作为SqlConnectionSqlCommand实现IDisposable接口,using块将处理CloseDispose方法。

于 2013-03-26T14:17:45.800 回答