Reputation: 887
I am using PowerShell version 5, I want to Add the BulkCopy command in the Transaction block, so that if at all there are any issues while copying data from 1 server to another, then nothing should be committed.
Below is my code, where Transaction works for other multiple SQL Commands (Create, Insert) so if anything fails while inserting table is also not created. But same is not working for the BulkCopy command.
Script
$SrcconnString = "Data Source=<Server-Name>;Database=<DB-Name>;User ID=<Login>;Password=<Pass>"
$TrgconnString = "Data Source=<Server-Name>;Database=<DB-Name>;User ID=<Login>;Password=<Pass>"
$error.clear()
$TrgTblName = 'dbo.test'
$BulkCopyTimeout = '1000'
$BulkCopyBatchSize = '20000'
Import-Module -Name SQLServer
write-host 'module loaded'
#Create a SQL connection object
$Srcconn = New-Object System.Data.SqlClient.SqlConnection $SrcconnString
$Trgconn = New-Object System.Data.SqlClient.SqlConnection $TrgconnString
#Attempt to open the connection
$Srcconn.Open()
$Trgconn.Open()
$tran = $Trgconn.BeginTransaction()
try
{
if($Srcconn.State -eq "Open" -And $Trgconn.State -eq "Open" )
{
Write-Host "connection successful"
<# Below Commented block works for Transaction #>
<#
$script = @"
DROP Table IF EXISTS dbo.test_bulk;
Create table dbo.test_bulk (Id int, Name varchar(2));
INSERT INTO dbo.test_bulk(Id,name) Values (1,'vj'),(2,'jgjeguegjeg');
"@
$cmd = New-Object System.Data.SqlClient.SqlCommand($script, $Trgconn)
$cmd.Transaction = $tran
[void]$cmd.ExecuteNonQuery()
$tran.Commit()
#>
$sql = "SELECT top 100 * FROM dbo.test(NOLOCK)";
$sqlCommand = New-Object system.Data.SqlClient.SqlCommand($sql, $Srcconn)
[System.Data.SqlClient.SqlDataReader] $sqlReader = $sqlCommand.ExecuteReader()
$bulkCopy = New-Object Data.SqlClient.SqlBulkCopy($TrgconnString, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity,$tran)
$bulkCopy.DestinationTableName = $TrgTblName
$bulkCopy.BulkCopyTimeOut = $BulkCopyTimeout
$bulkCopy.BatchSize = $BulkCopyBatchSize
$bulkCopy.WriteToServer($sqlReader)
$tran.Commit()
$sqlReader.Close()
$bulkCopy.Close()
}
}
catch
{
$tran.Rollback()
#Write-Host "Operation failed"
#$error
$_.exception.message
}
finally
{
$Srcconn.Close()
$Trgconn.Close()
$error.clear()
}
Update: After @DanGuzman comment, I Specified the transaction object ($tran) as the third parameter for the SqlBulkCopy command,
$bulkCopy = New-Object Data.SqlClient.SqlBulkCopy($TrgconnString, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity,$tran)
but now it fails with an error
Exception calling "WriteToServer" with "1" argument(s): "WriteToServer requires an open and available connection. The Connection's current state is closed."
Upvotes: 0
Views: 1964
Reputation: 1
I got similar setup working when passing the actual connection instead of connection string as the first parameter.
In your example it would be:
$bulkCopy = New-Object Data.SqlClient.SqlBulkCopy($Trgconn, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity,$tran)
Upvotes: 0