0

我正在 ASP.Net 中执行提交例程。问题是,在调试 try-catch 块中的代码时,如果我/用户遇到错误,SQL 事务永远不会回滚。

如果我在两者之间中断此提交例程,SQL Server 2008 将完全挂起。即使从 SSMS 我也无法进行选择/插入操作。最后,我必须重新启动 SQL Server 才能回滚事务。

提交代码:

SqlConnection conn = Db.getConn();
if (conn.State == ConnectionState.Closed) conn.Open();

SqlTransaction trn;
trn = conn.BeginTransaction();

SqlCommand sqlCmd = new SqlCommand("", conn);
sqlCmd.Transaction = trn;

try
{
    string query = GetQuery(); // works fine
    sqlCmd.CommandText = query;

    sqlCmd.ExecuteNonQuery();


    using (SqlBulkCopy bcp = new SqlBulkCopy(conn,SqlBulkCopyOptions.Default, trn))        
        {
            bcp.ColumnMappings.Add("FaYear", "FaYear");
            bcp.ColumnMappings.Add("CostCode", "CostCode");
            bcp.ColumnMappings.Add("TokenNo", "TokenNo");

            bcp.DestinationTableName = "ProcessTokenAddress";
            bcp.WriteToServer(globaltblAddress.DefaultView.ToTable());
        }
    trn.commit();
}
catch (SqlException ex)
{
   trn.Rollback();
}

注意:就在这里编写代码时,我意识到我已经捕获了 SqlException而不是Exception。这是导致错误的原因吗?呸?

重要提示:我是否需要在 Page_UnLoad 或其他一些可以处理意外情况的事件处理程序中回滚事务(例如,用户在事务进行时关闭浏览器,用户点击后退按钮等)。

4

1 回答 1

1

首先,在 .Net 中,您不应该维护一个打开的连接,您会一遍又一遍地重复使用它。这样做的结果实际上正是您所经历的——在应该关闭连接的情况下,它不是。

二是连接实现IDisposable。这意味着它们应该在一个using语句或一个try-catch带有finally显式关闭连接的块中创建和使用。如果您有一个类本身实现IDisposable并在其生命周期内保持连接,然后在释放连接时关闭连接,则可以打破此规则。

您可能会想通过不一直打开和关闭连接来提高效率。事实上,您会误会,因为 .Net 会为您处理连接池。标准做法是让您传递连接字符串,而不是打开连接对象。您可以将连接字符串包装在将为您返回新连接的类中,但您不应该维护打开的连接。这样做可能会导致您遇到的错误。

因此,请执行以下操作:

  1. 使用using声明。这将在创建和使用它们后正确清理您的连接。

    using (SqlConnection conn = Db.getConn()) {
        conn.Open();
        // your code here
    }
    
  2. 您必须检查连接是否打开的事实表明了问题所在。不要这样做。相反,更改您的Db类中的代码以每次分发一个新创建的连接。然后你可以确定状态会关闭,你可以自信地打开它。或者,在您的Db类中打开连接,但命名您的方法以指示连接将打开,例如GetNewOpenConnection. (尽量避免方法名和类名的缩写。)

  3. 我会建议你throw错误。虽然记录它而不是抛出它是一种可能的选择,但在用户坐在计算机前期待结果的任何情况下,简单地吞下错误将不是正确的操作,因为您以后的代码将如何知道发生了错误并让用户知道?一些将异常信息传递给用户的方法是必要的。最好不要处理异常,而不是默默地吞下它。

最后,一点样式说明是getConn()不遵循 C# 社区中发现的和 Microsoft 推荐的正常大写做法。类中的公共方法应以大写字母开头:GetConn().

于 2017-04-20T21:32:04.413 回答