13

如何确保以下语句在一个事务中运行?

try
{
  Invoke-SqlCmd -Query 'begin tran; ...sql script...'
  # Other Powershell script
  Invoke-SqlCmd -Query '...sql script...; if @@transcation > 0 commit tran' 
}
catch 
{
   Invoke-SqlCmd -Query 'if @@transaction > 0 rollback tran;'
}

在事务中运行 Powershell 脚本的最佳方法是什么?

4

5 回答 5

16

不幸的是,SqlProvider在 Powershell 中没有Registry提供者那样的事务能力。因此Start-transaction不会在这里工作。

您可以原生并利用TransactionScope类。

Try{
   $scope = New-Object -TypeName System.Transactions.TransactionScope

   Invoke-Sqlcmd -server Darknite -Database AdventureWorks2008 -Query $Query1 -ea stop
   Invoke-Sqlcmd -server Darknite -Database AdventureWorks2008 -Query $Query2 -ea stop

   $scope.Complete() 
}
catch{
    $_.exception.message
}
finally{
    $scope.Dispose() 
}

所有位于 $scope 赋值 和 之间的 Invoke-sqlcmd 都$scope.complete()将被视为一个事务。如果其中任何一个出错,所有内容都将回滚。

于 2015-01-13T06:53:42.813 回答
5

Nitesh举了一个很好的例子,帮助了我,谢谢!要添加的一件事是 Scope.Complete() 不会将事务提交发送到数据库。如果您在循环中使用此代码,这将是显而易见的。

提交最终使用您的范围执行,因此确保提交的工作示例将在完成后添加显式处置,如下所示:

$scope.Complete();
$scope.Dispose();

查看详情 TransactionScope Complete() 在退出 USING 语句之前不提交事务

于 2016-09-28T04:10:01.810 回答
4

Invoke-sqlcmd 不支持 ADO.NET 事务。您有两种解决方法,或者将等效的 Powershell 代码写入此 MSDN 文档中针对 ADO.NET 事务显示的 C# 代码:http: //msdn.microsoft.com/en-us/library/2k2hy99x(v=vs.110) .aspx

或者使用 T-SQL 事务。在不向每个脚本添加 T-SQL Try/Catch 的情况下执行此操作的一种快速方法是将 XACAT_ABORT 设置为 ON;然后将脚本包装在开始并提交事务。请记住,这可能无法捕获终止错误:

http://msdn.microsoft.com/en-us/library/ms188792.aspx

于 2012-12-20T19:17:07.690 回答
2

我最近发布了一个新模块,用于与支持事务的数据库进行交互:

Install-Module -Name InvokeQuery

如果发生错误,您不需要显式回滚。创建的环境事务Start-Transaction将为您处理。

try {
    $db = "test"
    Start-Transaction

    $sql = "insert into table1 values (NEWID(), 8765, 'transactions!', GETDATE())"
    $rowcount = $sql | Invoke-SqlServerQuery -Database $db -UseTransaction -CUD -Verbose
    Write-Host "Inserted $rowcount rows!"

    $sql = "insert into table1 values (NEWID(), 5555, 'transaction too!', GETDATE())"
    $rowcount = $sql | Invoke-SqlServerQuery -Database $db -UseTransaction -CUD -Verbose
    Write-Host "Inserted $rowcount rows!"

    Complete-Transaction
}
catch {
    ##Transaction will automatically be rolled back....
    Write-Error $_
}

如果要在事务中显式回滚,则抛出错误:

throw 'rollback because of reason X!'

更多示例: https ://github.com/ctigeek/InvokeQueryPowershellModule/blob/master/README.md#transactions

于 2016-05-10T21:13:32.683 回答
0

我建议检查Invoke-SqlCmd2,它采用现有 SqlConnection 的参数。

安装:

Install-Module Invoke-SqlCmd2 -Scope CurrentUser

将其与事务一起使用将如下所示:

$Connection = [System.Data.SqlClient.SqlConnection]::new($ConnectionString)
$Connection.Open()
$Transaction = $Connection.BeginTransaction()

try {
   Invoke-SqlCmd2 -SqlConnection $Connection -Query "..." -ErrorAction Stop
   Invoke-SqlCmd2 -SqlConnection $Connection -Query "..." -ErrorAction Stop
   $Transaction.Commit()
}
catch {
   $Transaction.Rollback()
}
finally {
   $Connection.Close()
}
于 2021-11-01T16:37:05.673 回答