我有以下使用交易的方法。
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();
然后出现以下错误。
此SqlTransaction已完成;它不再可用了
如何关闭连接以避免错误?
答案 0 :(得分:3)
您无法使用单个连接耗尽游泳池。您需要关闭所有正在使用的连接。优选地在之后,交易以这种或那种方式结束。几乎所有与数据库相关的对象都是using
块。
顺便说一下:
throw ex;
这会通过更换原始堆栈跟踪来损害您的例外。使用:
throw;
重新抛出你没有改变的例外。
答案 1 :(得分:1)
如上所述,您应该正确处理连接。我已修改您的代码以进行演示。请注意,您需要将连接字符串替换为您的连接字符串。
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块中抛出异常,则会发生回滚并且异常向上传递到堆栈。
答案 2 :(得分:-1)
你有没有考虑过CALLNIG关闭?关闭连接或?
是显而易见的任何实现IDIsposable的东西都应该被处理,顺便说一下,而不仅仅是关闭。并且SqlConnection实现了IDisposable。这与SqlTransaction无关 - 你通过不处理一次性例程来违反.NET世界的基本规则。