使用事务时关闭连接

cha*_*ara 0 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;
            }

    }
Run Code Online (Sandbox Code Playgroud)

多次运行该方法后,用户最终收到以下错误消息。

在从池中获取连接之前经过的超时时间

发生错误是因为我尚未关闭连接并且连接池已溢出。

我尝试在提交事务之前关闭连接。

transaction.Connection.Close();  
transaction.Commit();
Run Code Online (Sandbox Code Playgroud)

然后得到以下错误。

这个SqlTransaction已经完成;它不再可用

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

nvo*_*igt 5

您无法使用单个连接耗尽池。您需要关闭正在使用的所有连接。最好交易以一种或另一种方式结束之后using块是几乎所有与数据库相关的对象的朋友。

顺便一提:

throw ex;
Run Code Online (Sandbox Code Playgroud)

这会通过替换原始堆栈跟踪来破坏您的异常。用:

throw;
Run Code Online (Sandbox Code Playgroud)

重新抛出您捕获的未更改的异常。


Joh*_*ger 5

如前所述,您应该正确处理连接。我修改了你的代码来演示。请注意,您需要将连接字符串替换为您的连接字符串。

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. 
}
Run Code Online (Sandbox Code Playgroud)

建立新的连接成本低廉,不应该被拒绝。每一个称为数据库的数据库都应该像这样打开一个新数据库。通过维护连接而不是释放它,您也会从数据库中夺走资源。它的池中没有可以立即使用的无限数量的连接。

编辑

删除了评论中提到的 try/catch。如果在 using 块中抛出异常,则会发生回滚并且异常会在堆栈中传递。

  • 不,事务由 using 块处理,导致回滚。异常会正常传递,并且可以在更高级别捕获。这就是使用块的要点:它们*将*处理该对象,无论它们如何留下。 (2认同)