【问题标题】:TransactionScope doesn't rollback a queryTransactionScope 不回滚查询
【发布时间】:2016-04-28 12:17:34
【问题描述】:

我有 2 个查询必须一起工作。第一个是 Update,第二个是 Insert 查询。我将它们放入 TransactionScope 范围:

using (TransactionScope scope = new TransactionScope())
{
    SqlCommand updateCmd = new SqlCommand("UPDATE V_Stock SET Quantity= 5 WHERE Id=" + shelfId, con);
    SqlCommand insertCmd = new SqlCommand("INSERT INTO V_Stock (Code, Quantity,   Name) VALUES (@1, @2, @3)", con);
    insertCmd.Parameters.AddWithValue("@1", "Code1");
    insertCmd.Parameters.AddWithValue("@2", 15);
    insertCmd.Parameters.AddWithValue("@3", "Name1");
    try
    {
        updateCmd.ExecuteNonQuery();
        insertCmd.ExecuteNonQuery();            
    }
    catch (Exception ex)
    {
        scope.Complete();
        string s = ex.ToString();
    }
}

更新查询可以正常工作,但插入查询不能。在这种情况下,我不想执行它们。只有当它们正常工作时才应该执行它们。

我可以做些什么来一起处理这些查询?

【问题讨论】:

  • 删除scope.Dispose() 行, using() 将为您完成此操作。还有为什么你在 catch 中需要 s 变量?也许缺少日志记录?
  • 调用scope.Dispose() 是不必要的,using 已经这样做了。但是,您确实需要在查询完成后显式调用scope.Complete(),否则范围回滚。此外,不清楚“不回滚”和“一起工作”是什么意思。您想要实现什么目标以及实际发生了什么?
  • 另外,调用ExecuteNonQuery后,需要调用scope.Complete()提交事务。
  • 在 ExecuteNonQuery() 之后使用 scope.Complete() 也不起作用

标签: c# sql asp.net transactionscope


【解决方案1】:
  • 您需要在准备好提交事务时调用scope.Complete,而不是在事务失败时。
  • 您还应该在TransactionScope 范围内打开连接,以便在该范围内注册连接。
  • 我也不确定你的SqlConnection 实例是在哪里定义的。 Microsoft 团队始终建议您使用短期连接,使用它们并摆脱它们。让 Sql Server 处理连接池(通常默认情况下启用),这使得在 c# 代码中使用和丢弃 sql 连接非常便宜。

这是一些重构的代码,我添加了一些文档,这些文档是在 Microsoft 定义中找到的 TransactionScope

using (TransactionScope scope = new TransactionScope())
{
    using (SqlConnection con = new SqlConnection(yourConnectString))
    {
        // according to the documentation on TransactionScope
        // Opening the connection automatically enlists it in the 
        // TransactionScope as a lightweight transaction.
        con.Open();

        // I changed this to make it parameterized as well although this had nothing to do with the TransactionScope question
        SqlCommand updateCmd = new SqlCommand("UPDATE V_Stock SET Quantity= 5 WHERE Id= @shelfId", con);
        updateCmd.Parameters.AddWithValue("@shelfId", shelfId);

        SqlCommand insertCmd = new SqlCommand("INSERT INTO V_Stock (Code, Quantity, Name) VALUES (@1, @2, @3)", con);
        insertCmd.Parameters.AddWithValue("@1", "Code1");
        insertCmd.Parameters.AddWithValue("@2", 15);
        insertCmd.Parameters.AddWithValue("@3", "Name1");

        updateCmd.ExecuteNonQuery();
        insertCmd.ExecuteNonQuery();            

        // according to the documentation on TransactionScope
        // The Complete method commits the transaction. If an exception has been thrown,
        // Complete is not  called and the transaction is rolled back.
        scope.Complete();
    }
}

【讨论】:

    猜你喜欢
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    相关资源
    最近更新 更多