2013-03-26 96 views
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(); 
    } 
} 
+1

您应该阅读这篇文章。它很好地解释了它; http://msdn.microsoft.com/en-GB/library/yh598w02.aspx。特别是,看一下代码片段,它显示了编译器实际将使用的“using”语句的内容。 – 2013-03-26 14:17:52

+1

try/catch/finally是在iDisposable对象内执行的,所以在这种情况下不需要执行try/catch/finally。如果你有其他一些需要捕获/最终用于其他目的的逻辑,你可能仍然需要它。但在这种情况下,你所做的基本上都是复制出售给你的东西。除了在第二个代码示例中你正在吞咽任何有问题的错误。 =) – 2013-03-26 14:18:40

回答

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这意味着当您在SqlConnection上调用.Open()方法时,您不打开与数据库的物理连接。你只是从游泳池中抽取一个。当您调用.Close(或.Dispose)方法时,您并未关闭连接。您只需将它返回到连接池,以便它可以重用。

+0

但conn和cmd都是一次性的?对?哪一个我包装在使用声明? :) – 2013-03-26 14:17:13

+1

他们两个。看到我的答案。 – 2013-03-26 14:17:42

+0

谢谢!所以在这种情况下,我仍然使用conn.Open(),但它在到达使用块的末尾时会自动关闭?正确? – 2013-03-26 14:22:01

0

你不会有,如果你把它放到使用块关闭连接。使用块用于实现IDisposable的对象。 IDisposable允许对象在被GC收集之前清除非托管资源。这释放了内存并允许GC收集该对象。

0

使用块只是一个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(); 
} 
0

你应该有一对夫妇使用块在这里,实际上,自SqlConnectionSqlCommand都实现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. 
     } 
    } 
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方法。