2012-09-14 38 views
0

我们正在尝试实施一个修补客户端软件的程序 - 最初将运行一个.SQL,但如果脚本在任何时候都失败,我们将回滚数据库并停止客户端DLL导入过程从工作。通过多个数据库上的事务执行SQL脚本

我们的SQL脚本具有“GO”语句,因此我们无法将使用sp_executesql的漂亮存储过程放在一起,因为这不允许“GO” - 相反,如果我们有一个如下所示的SQL脚本:

USE [SomeDatabase] 

BEGIN TRANSACTION 
GO 
IF (OBJECT_ID(N'[dbo].[ProcedureToUpdate]') IS NOT NULL) 
    DROP PROCEDURE [dbo].[ProcedureToUpdate] 
GO 
IF @@ERROR <> 0 
    AND @@TRANCOUNT > 0 
    ROLLBACK TRAN 
GO 
IF @@TRANCOUNT = 0 
    BEGIN 
     --Flag that the procedure hasn't been dropped, begin another transaction 
     BEGIN TRANSACTION 
    END 
GO 

PRINT 'Creating procedure' 
GO 

CREATE PROCEDURE [dbo].[ProcedureToUpdate] 
AS 
    SELECT * 
    FROM [dbo].[SomeTable] st 
      INNER JOIN [dbo].[AnotherTable] at ON st.PK = at.fk 

GO 

IF @@ERROR <> 0 
    AND @@TRANCOUNT > 0 
    ROLLBACK TRAN 
GO 
IF @@TRANCOUNT = 0 
    BEGIN 
     --Flag that the procedure hasn't been created, begin another transaction 
     BEGIN TRANSACTION 
    END 
GO 

然后,我们正在执行在.NET中有问题的数据库事务中的每个“动作”(由go语句拆分) - 如果循环内部出现任何故障,这将回滚数据库。

Using con As New SqlConnection(ConnectionString) 
    con.Open() 
    Dim cmd As SqlCommand = con.CreateCommand() 
    Dim transaction As SqlTransaction = con.BeginTransaction("Upgrade") 
    cmd.Connection = con 
    cmd.Transaction = transaction 
    Try 
     For Each transactionalScript In transactionalScripts 
     cmd.CommandText = transactionalScript 
     Dim result = cmd.ExecuteNonQuery() 
     Next 
     transaction.Commit() 
    Catch ex As Exception 
     Log(String.Format("{0} : Script Failed", DateTime.Now.ToString())) 
     Log(String.Format("{0} : Reason: {1}", DateTime.Now.ToString(), ex.Message)) 
     transaction.Rollback("Upgrade") 
     Log(String.Format("{0} : Database rolled back", DateTime.Now.ToString())) 
    End Try 
    End Using 

最后 - 这是我的问题。我们需要处理多达4个.SQL脚本,每个脚本将用于单个服务器上的不同数据库。如果4个脚本中的任何一个发生故障,我们应该回滚脚本受到影响的每个数据库 - 有什么建议吗?

回答

0

看看使用TransactionScope

如果您在TransactionScope内使用多个连接,则会发布分布式事务。这有它自己的要求(如DTC),但这当然是你想要开始寻找的地方。

相关问题