【问题标题】:Ensure all updates are successfully complete?确保所有更新都成功完成?
【发布时间】:2013-03-20 19:39:38
【问题描述】:

当提交新表单时,我有一些存储过程可以对几个表进行各种更新和插入。它们都是从我拥有的 C# 应用程序中调用的。

现在所有内容都采用try catch 格式,有什么方法可以确保在实际将更改提交到数据库之前成功完成所有操作?

假设前 3 个存储过程一切正常,但第 4 个存储过程失败,我想扭转前 3 个存储过程中已经完成的操作。

全有或全无类型的交易。

【问题讨论】:

    标签: c# asp.net .net sql-server sql-server-2008


    【解决方案1】:

    您需要使用TransactionScope 类(System.Transactions.TransactionScope)

    //assuming Table1 has a single INT column, Column1 and has one row with value 12345
    //and connectionstring contains a valid connection string to the database.
        //this automatically starts a transaction for you
    try
    {
                using (TransactionScope ts = new TransactionScope())
                {
            //you can open as many connections as you like within the scope although they need to be on the same server. And the transaction scope goes out of scope if control leaves this code.
                   using (SqlConnection conn = new SqlConnection(connectionstring))
                   {
                      conn.Open();
                      using (SqlCommand comm = new SqlCommand("Insert into Table1(Column1) values(999)")
                      {
                        comm.ExecuteNonQuery();
                      }
                       using (SqlCommand comm1 = new SqlCommand("DELETE from Table1 where Column1=12345"))
                       {
                         comm1.ExecuteNonQuery();
                       }
                    }//end using conn
                   ts.Complete() ; //commit the transaction; Table1 now has 2 rows (12345 and 999) 
                }//end using ts
    
    }
      catch(Exception ex)
       {
         //Transaction is automatically rolled back for you at this point, Table1 retains original row.
       }
    

    【讨论】:

    • 虽然这可以给出一个正确的答案,但人们普遍认为应该以评论的形式给出仅链接的答案,或者至少报告一些代码以避免link rot
    • @Steve - 很公平,帖子更新了更多细节
    • +1 现在我真的很喜欢它。这是最好的答案,至少对我来说。
    【解决方案2】:

    我不确定你是如何配置它的;但您显然可以使用SqlException 类。但另一种方法可能是:

    int result = command.ExecuteNonQuery();
    if(result == 1)
    {
        // Successfully Entered A Row
    }
    else
    {
        // Insert Row Failed
    }
    

    这是一种可能的测试方法。本质上它是在测试查询,如果它带回一行,那么它成功,如果没有,它就会失败。我不确定它是否符合您的标准,但这是您可以测试的两种方式。


    更新:

    因为我看不懂-但我相信您想实现Transactioning 的形式。这实际上将处理所有请求,如果失败,它将回滚更改。它确实增加了很多开销,在某些情况下可能会导致其他性能问题。因此,您需要根据需要定制和优化数据库吞吐量。

    这里有一些信息from MSDN on it

    希望对您有所帮助。

    【讨论】:

    • @MadamZuZu 是的,我相信。我在我们的一个应用程序中使用了它,我们不得不进行大量重构来优化它。
    【解决方案3】:

    我会为您在前 3 个中添加的新项目捕获唯一键,如果您失败了,只需根据这些键删除。

    【讨论】:

      【解决方案4】:

      你应该阅读这篇文章

      wiki:Database transaction

      还有这个

      msdn:Writing a Transactional Application

      【讨论】:

        猜你喜欢
        • 2019-02-14
        • 2021-02-18
        • 2014-11-14
        • 2013-04-14
        • 1970-01-01
        • 2022-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多