一个事务包含多个存储过程,经测试如果出现异常绝对可以回滚到起点

'1个事务,a.事务: 创建账单(父类),  此时会自动创建子类(这个账单包括哪些收费项目) b.根据上传的数据,修改收费项目应该对应的值

Public Shared Function AddUploadInditexBillSpecial(ByVal generalColCount As Integer, ByVal dsUploadData As DataSet, ByVal relationName As String) As String
        Dim conn As SqlConnection
        Dim cmd As SqlCommand
        Dim tranAddBillSpecial As SqlTransaction
        Dim sqlda As SqlDataAdapter
        Dim dsNewBillData As DataSet
        Const STR_MAIN_TRANSACTION_NAME As String = "AddBillSpecial"
        Dim i As Integer = 0
        Dim ds As New DataSet

        Try
            Dim importData As DataTable = dsUploadData.Tables(0)
            Dim importDetailData As DataTable = dsUploadData.Tables(1)
            conn = New SqlConnection(DataSqlHelp.connection)
            conn.Open()
            tranAddBillSpecial = conn.BeginTransaction(STR_MAIN_TRANSACTION_NAME)
            For rowIndex As Integer = 0 To importData.Rows.Count - 1

                Dim row As DataRow = importData.Rows(rowIndex)

                '1.创建账单(a存储过程)
                cmd = New SqlCommand("SP_AddInditexBillSpecial", conn)
                cmd.CommandType = CommandType.StoredProcedure
                cmd.Transaction = tranAddBillSpecial
                cmd.CommandTimeout = 0


                cmd.Parameters.AddWithValue("@SupplierID", row("SupplierID").ToString().Trim())
                cmd.Parameters.AddWithValue("@Customer", row("Customer").ToString().Trim())
                cmd.Parameters.AddWithValue("@Location", row("Location").ToString().Trim())
                cmd.Parameters.AddWithValue("@BillType", row("BillType").ToString().Trim())
                cmd.Parameters.AddWithValue("@TransMode", row("TransMode").ToString().Trim())
                cmd.Parameters.AddWithValue("@BillMonth", row("BillMonth").ToString().Trim())
                cmd.Parameters.AddWithValue("@OperationTime", Convert.ToDateTime(row("OperationTime")).ToString("yyyyMMdd"))

                Dim paramNewBillId As SqlParameter = New SqlParameter("@newBillID", SqlDbType.NVarChar, 20)
                paramNewBillId.Direction = ParameterDirection.Output
                cmd.Parameters.Add(paramNewBillId)
                Dim paramErrorMsg As SqlParameter = New SqlParameter("@ErrorMsg", SqlDbType.NVarChar, 200)
                paramErrorMsg.Direction = ParameterDirection.Output
                cmd.Parameters.Add(paramErrorMsg)


                sqlda = New SqlDataAdapter(cmd)
                dsNewBillData = New DataSet()
                sqlda.Fill(dsNewBillData)

                '2.更改Detail(b存储过程)
                If paramErrorMsg.Value = String.Empty Then
                    If (Not dsNewBillData.Tables(0) Is Nothing) AndAlso dsNewBillData.Tables(0).Rows.Count > 0 Then
                        Dim detailRows As DataRow() = row.GetChildRows(relationName)
                        If (Not detailRows Is Nothing) AndAlso detailRows.Length > 0 Then
                            For Each detailRow As DataRow In detailRows
                                Dim newBillDetailRow As DataRow = dsNewBillData.Tables(0).Select(String.Format("ChargeCode='{0}'", detailRow("ChargeCode").ToString().Trim()))(0)
                                For Each col As DataColumn In importDetailData.Columns
                                    If detailRow(col.ColumnName) Is Nothing OrElse detailRow(col.ColumnName) Is DBNull.Value Then
                                        detailRow(col.ColumnName) = newBillDetailRow(col.ColumnName)
                                    End If
                                Next

                                cmd = New SqlCommand("SP_UpdateBillSpecialDetail", conn)
                                cmd.CommandType = CommandType.StoredProcedure
                                cmd.Transaction = tranAddBillSpecial
                                cmd.CommandTimeout = 0

                                cmd.Parameters.AddWithValue("@SupplierID", detailRow("SupplierID").ToString())
                                cmd.Parameters.AddWithValue("@Cost", detailRow("Cost").ToString())
                                cmd.Parameters.AddWithValue("@Cost_UnitPrice", detailRow("Cost_UnitPrice").ToString())
                                cmd.Parameters.AddWithValue("@Cost_Qty", detailRow("Cost_Qty").ToString())
                                cmd.Parameters.AddWithValue("@Cost_InvoiceNo", DBNull.Value)
                                cmd.Parameters.AddWithValue("@Cost_Note", IIf(detailRow("Cost_Note") Is DBNull.Value, DBNull.Value, detailRow("Cost_Note").ToString()))
                                cmd.Parameters.AddWithValue("@Revenue", detailRow("Revenue").ToString())
                                cmd.Parameters.AddWithValue("@Revenue_UnitPrice", detailRow("Revenue_UnitPrice").ToString())
                                cmd.Parameters.AddWithValue("@Revenue_Qty", detailRow("Revenue_Qty").ToString())
                                cmd.Parameters.AddWithValue("@Revenue_InvoiceNo", DBNull.Value)
                                cmd.Parameters.AddWithValue("@accrualCost", DBNull.Value)
                                cmd.Parameters.AddWithValue("@accrualRevenue", DBNull.Value)
                                cmd.Parameters.AddWithValue("@Note", IIf(detailRow("Note") Is DBNull.Value, DBNull.Value, detailRow("Note").ToString()))
                                cmd.Parameters.AddWithValue("@BillSpecialDetailID", detailRow("BillSpecialDetailID").ToString())
                                cmd.Parameters.AddWithValue("@Operator", detailRow("Operator").ToString())
                                cmd.ExecuteNonQuery()
                            Next
                        End If
                    Else
                        Throw New Exception("Create Bill Failed")
                    End If
                Else
                    Throw New Exception(paramErrorMsg.Value)
                End If
                i = i + 1
            Next

            tranAddBillSpecial.Commit()
        Catch ex As Exception
            tranAddBillSpecial.Rollback()
            Return ex.Message
        Finally
            conn.Close()
            conn.Dispose()
        End Try

        Return String.Empty
    End Function

### 回答1: 请参考以下SQL Server存储过程示例,它可以带有异常处理和回滚:CREATE PROCEDURE [dbo].[usp_example] AS BEGIN BEGIN TRY BEGIN TRANSACTION -- Your T-SQL Statements Here COMMIT TRANSACTION END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION END CATCH END ### 回答2: 下面是一个使用SQL Server的带有异常回滚事务存储过程示例,它用于在插入订单和订单明细时保持数据的一致性和完整性。 ``` CREATE PROCEDURE sp_InsertOrder @CustomerID INT, @OrderDate DATE, @ProductID INT, @Quantity INT AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; -- 插入订单 INSERT INTO Orders (CustomerID, OrderDate) VALUES (@CustomerID, @OrderDate); -- 获取刚刚插入的订单ID DECLARE @OrderID INT = SCOPE_IDENTITY(); -- 插入订单明细 INSERT INTO OrderDetails (OrderID, ProductID, Quantity) VALUES (@OrderID, @ProductID, @Quantity); COMMIT TRANSACTION; -- 提交事务 END TRY BEGIN CATCH IF @@TRANCOUNT > 0 BEGIN ROLLBACK TRANSACTION; -- 回滚事务 END -- 输出错误信息 SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine; END CATCH; END; ``` 在此存储过程中,我们首先使用`BEGIN TRY`和`BEGIN CATCH`块来捕捉可能发生的异常。若异常发生,则通过`ROLLBACK TRANSACTION`语句将事务回滚到之前的状态。 如果没有异常发生,事务会在`COMMIT TRANSACTION`语句处被提交,确保订单和订单明细同时插入,保持数据的一致性。 在`CATCH`块中,我们还可以输出有关异常的详细信息,如错误代码、错误消息、错误存储过程和错误行号等,以便进行故障排除和错误处理。 要使用此存储过程,只需向其传递正确的参数值即可。例如: ``` EXEC sp_InsertOrder 1, '2021-01-01', 100, 5; ``` 以上示例调用了存储过程`sp_InsertOrder`,将`CustomerID`设为1,`OrderDate`设为2021年1月1日,`ProductID`设为100,`Quantity`设为5。如果没有异常发生,订单和订单明细将被成功插入,否则事务将被回滚并输出异常信息。 ### 回答3: 以下是一个带有异常回滚事务功能的SQL Server存储过程示例: ```sql CREATE PROCEDURE [dbo].[usp_ExampleProc] AS BEGIN SET NOCOUNT ON; SET XACT_ABORT ON; BEGIN TRY BEGIN TRANSACTION; -- 执行多个SQL语句来完成业务逻辑 -- 例如插入数据到表A INSERT INTO [dbo].[TableA] (Column1, Column2) VALUES ('Value1', 'Value2'); -- 例如更新数据表B UPDATE [dbo].[TableB] SET Column1 = 'NewValue' WHERE Column2 = 'OldValue'; -- 事务提交 COMMIT TRANSACTION; END TRY BEGIN CATCH -- 如果发生异常,回滚事务 ROLLBACK TRANSACTION; -- 根据需要,可以记录异常信息到日志表或返回自定义错误消息 -- 例如:INSERT INTO [dbo].[ErrorLog] (ErrorMessage, ErrorDateTime) VALUES (ERROR_MESSAGE(), GETDATE()) -- 抛出异常或返回错误消息给调用者 THROW; END CATCH; END ``` 上述存储过程使用 `BEGIN TRANSACTION` 来开启一个事务,在 `TRY` 块内执行需要进行的操作,并在 `CATCH` 块内捕获异常并进行回滚操作。同时,代码中使用 `SET XACT_ABORT ON` 来确保在发生异常时可以自动回滚事务。你可以根据实际需求,在 `TRY` 块中编写需要执行的SQL语句以完成业务逻辑,并根据需要在 `CATCH` 块中记录异常信息或返回自定义错误消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值