使用事务时关闭连接

时间:2014-06-02 05:46:46

标签: c# asp.net asp.net-mvc transactions

我有以下使用交易的方法。

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已完成;它不再可用了

如何关闭连接以避免错误?

3 个答案:

答案 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世界的基本规则。