为什么在SqlTransaction中使用using语句?

我一直在遇到一些关于我在我的代码中使用的SqlTransaction的问题。 在我的谷歌search中,我看到许多人使用一个SqlTransaction使用语句。

在SqlTransaction中使用这种types的语句的好处和/或区别是什么?

using (SqlConnection cn = new SqlConnection()) { using (SqlTransaction tr = cn.BeginTransaction()) { //some code tr.Commit(); } } 

目前我的代码如下所示:

 SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"]); cn.Open(); SqlTransaction tr = cn.BeginTransaction(); try { //some code tr.Commit(); cn.Close(); } catch(Exception ex) { tr.Rollback(); cn.Close(); throw ex; } 

一种方式的优点是什么?

每次创build一个在块范围内实现IDisposable的类的实例时,都应该using语句。 它确保将在该实例上调用Dispose()方法,无论是否引发exception。

特别是,你的代码只捕获托pipe的exception,然后通过抛出一个新的exception而不是重新抛出现有的exception来破坏堆栈框架。

正确的方法是:

 using (SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"])) { cn.Open(); using (SqlTransaction tr = cn.BeginTransaction()) { //some code tr.Commit(); } } 

请注意,如果您的类具有实现IDisposabletypes的实例成员,那么您的类必须实现IDisposable本身,并在Dispose()调用期间处理这些成员。

原因是如果SqlTransaction对象没有显式提交(例如抛出exception),它将在其Dispose()方法中回滚。 换句话说,它和你的代码有相同的效果,只是一点点清洁。

基本上,使用和你在做的事情是一样的,除了int finally块,而不是捕获所有的exception:

 using (SqlConnection cn = new SqlConnection()) { using (SqlTransaction tr = cn.BeginTransaction()) { //some code tr.Commit(); } } 

是相同的,只是更less的代码:)

 { SqlConnection cn = null; try { cn = new SqlConnection(); { SqlTransaction tr = null; try { tr = cn.BeginTransaction()) //some code tr.Commit(); } finally { if(tr != null && tr is IDisposable) { tr.Dispose(); } } } } finally { if(cn != null && cn is IDisposable) { cn.Dispose(); } } } 

最后, using只是一种模式的捷径。 但这是一个非常有用和有用的捷径,因为它确保您正确实施模式,并且意味着您可以使用较less的代码来完成此操作。

在这种情况下,您尚未正确实施该模式。 如果对tr.RollBack()的调用也会引发exception, tr.RollBack()代码中会发生什么?

使用声明是closures和处置你的连接和交易。 这相当于在你的try / catch中有一个finally块来处理。

你也可以把使用块压缩一下

 using (SqlConnection cn = new SqlConnection()) using (SqlTransaction tr = cn.BeginTransaction()) { //some code tr.Commit(); } 

这将大致相同:

 SqlConnection cn = null; SqlTransaction tr = null; try { cn = new SqlConnection()); tr = cn.BeginTransaction()); //some code tr.Commit(); } finally { if (cn != null) cn.Dispose(); if (tr != null) tr.Dispose(); } 

如果不使用using()块,则必须显式调用SqlConnection和SqlTransaction对象的.Dispose()方法。 如果你不这样做,那么非托pipe资源将不会被释放,并可能导致内存泄漏或其他问题。

除此之外,它还会优化您的代码。 7行代码不比14行好看吗? 每当我看到一个使用块时,我都屏住呼吸。 就像那个高兴的臭味出来的那个小水雾。 嗯,我是一个高效的代码块。 看看我如何pipe理记忆,以及我眼中的赏心悦目。

使用保证你的连接对象将在代码返回后被处置。 Dispose对释放非pipe理资源非常有用,作为一个好习惯,如果一个对象实现了IDisposable,那么总是应该调用dispose方法

Using语句是正确处理资源的简写。 您可以在MSDN上的使用语句文章中find更多信息