C# 使用事务时关闭连接
我有以下使用事务的方法C# 使用事务时关闭连接,c#,asp.net,asp.net-mvc,transactions,C#,Asp.net,Asp.net Mvc,Transactions,我有以下使用事务的方法 private string getDocumentDetailsByNumber(string DocNumber) { SqlTransaction transaction = DALDBConnection.SqlConnection.BeginTransaction(); try { DataSet DocNum = new DataSet();
private string getDocumentDetailsByNumber(string DocNumber)
{
SqlTransaction transaction = DALDBConnection.SqlConnection.BeginTransaction();
try
{
DataSet DocNum = new DataSet();
string sDocNumber = "";
string[] taleNamesDoc = new string[1];
taleNamesDoc[0] = "docnumber";
SqlParameter[] paramDoc = new SqlParameter[1];
paramDoc[0] = new SqlParameter("@DocumentNumber", DocNumber.ToString().Trim());
SqlHelper.FillDataset(transaction, CommandType.StoredProcedure, "spGetDocumentDetailsByNumber", DocNum, taleNamesDoc, paramDoc);
string docTitle = DocNum.Tables["docnumber"].Rows[0][0].ToString();
transaction.Commit();
return docTitle;
}
catch (Exception ex)
{
transaction.Rollback();
throw ex;
}
}
transaction.Connection.Close();
transaction.Commit();
在多次运行该方法后,用户最终收到下面的错误消息
从服务器获取连接之前经过的超时时间
水池
发生错误,因为我尚未关闭连接,并且连接池已溢出
我尝试在提交事务之前关闭连接
private string getDocumentDetailsByNumber(string DocNumber)
{
SqlTransaction transaction = DALDBConnection.SqlConnection.BeginTransaction();
try
{
DataSet DocNum = new DataSet();
string sDocNumber = "";
string[] taleNamesDoc = new string[1];
taleNamesDoc[0] = "docnumber";
SqlParameter[] paramDoc = new SqlParameter[1];
paramDoc[0] = new SqlParameter("@DocumentNumber", DocNumber.ToString().Trim());
SqlHelper.FillDataset(transaction, CommandType.StoredProcedure, "spGetDocumentDetailsByNumber", DocNum, taleNamesDoc, paramDoc);
string docTitle = DocNum.Tables["docnumber"].Rows[0][0].ToString();
transaction.Commit();
return docTitle;
}
catch (Exception ex)
{
transaction.Rollback();
throw ex;
}
}
transaction.Connection.Close();
transaction.Commit();
然后得到以下错误
此事务已完成;它不再可用
如何关闭连接以避免错误?您是否考虑过呼叫关闭连接?很明显要关闭一个连接还是
顺便说一句,任何实现IDIsposable的东西都应该被处理掉,而不仅仅是关闭。SqlConnection实现了IDisposable。这与SqlTransaction无关-您违反了.NET世界的一条基本规则,不处理一次性例程。您不能使用单个连接耗尽池。您需要关闭所有正在使用的连接。最好在交易以某种方式结束之后。几乎所有与数据库相关的对象都可以使用块 顺便说一下:
throw ex;
这会通过替换原始stacktrace来破坏您的异常。使用:
throw;
要重新显示捕获的异常,请保持不变。如前所述,您应该正确地处理连接。我已经修改了你的代码来演示。请注意,您需要将连接字符串替换为您的
private string getDocumentDetailsByNumber(string DocNumber)
{
using (var connection = new SqlConnection("My Connection String"))
{
SqlTransaction transaction = connection.BeginTransaction();
DataSet DocNum = new DataSet();
string sDocNumber = "";
string[] taleNamesDoc = new string[1];
taleNamesDoc[0] = "docnumber";
SqlParameter[] paramDoc = new SqlParameter[1];
paramDoc[0] = new SqlParameter("@DocumentNumber", DocNumber.ToString().Trim());
SqlHelper.FillDataset(transaction, CommandType.StoredProcedure, "spGetDocumentDetailsByNumber", DocNum, taleNamesDoc, paramDoc);
string docTitle = DocNum.Tables["docnumber"].Rows[0][0].ToString();
transaction.Commit();
return docTitle;
} // Connection is disposed and cleaned up.
}
打开新的连接是廉价的,不应该被反对。每调用一个数据库,都应该像这样打开一个新数据库。通过维护连接而不是处理连接,您也将从数据库中带走资源。它的池中没有可以同时使用的无限数量的连接
编辑
删除了注释中提到的try/catch。如果在using块中引发异常,则将发生回滚,异常将向上传递到堆栈 您可以使用usingsqltransaction tran=newsqltransaction{//you code},因此如果我使用usingsqltransaction=DALDBConnection.SqlConnection.BeginTransaction{//my code},它会关闭连接吗?在return语句之后它是否仍然关闭连接?不,它没有。连接本身应该在using块中。将事务也放在using块中,将摆脱整个异常处理。嗯,我想我从未在using块中遇到过异常。在块中抛出时是否吞没异常?否,事务由使用块处理,导致回滚。异常是正常传递的,可以在更高级别捕获。这就是使用块的意义所在:它们将处理对象,不管它们是如何留下的。感谢您的澄清。我没有意识到它会在抛出异常时自动处理回滚。这是一条很好的信息。SqlTransaction=connection.BeginTransaction;抛出无效的操作。连接已关闭。