Delen via


Bewerkingen voor transacties en bulksgewijs kopiëren

Bulksgewijs kopiëren kan worden uitgevoerd als geïsoleerde bewerkingen of als onderdeel van een transactie met meerdere stappen. Met deze laatste optie kunt u meerdere bulksgewijs kopiëren binnen dezelfde transactie uitvoeren en andere databasebewerkingen uitvoeren (zoals invoegen, updates en verwijderingen), terwijl u de hele transactie nog steeds kunt doorvoeren of terugdraaien.

Standaard wordt een bulksgewijze kopieerbewerking uitgevoerd als een geïsoleerde bewerking. De bulksgewijze kopieerbewerking vindt plaats op een niet-transacted manier, zonder de mogelijkheid om deze terug te draaien. Als u het bulkexemplaar of een deel van de bulkkopie wilt terugdraaien wanneer er een fout optreedt, kunt u een SqlBulkCopybeheerde transactie gebruiken, de bewerking voor bulksgewijs kopiëren uitvoeren binnen een bestaande transactie of worden opgenomen in een System.TransactionsTransaction.

Een niet-transacted bulkkopiebewerking uitvoeren

In de volgende consoletoepassing ziet u wat er gebeurt wanneer tijdens een niet-transacted bulkkopiebewerking een fout optreedt tijdens de bewerking.

In het voorbeeld bevatten de brontabel en doeltabel elk een Identity kolom met de naam ProductID. De code bereidt eerst de doeltabel voor door alle rijen te verwijderen en vervolgens één rij in te voegen waarvan de product-id bekend is in de brontabel. Standaard wordt een nieuwe waarde voor de Identity kolom gegenereerd in de doeltabel voor elke toegevoegde rij. In dit voorbeeld wordt een optie ingesteld wanneer de verbinding wordt geopend, waardoor het bulksgewijs laden wordt gedwongen de Identity waarden uit de brontabel te gebruiken.

De bulksgewijze kopieerbewerking wordt uitgevoerd met de BatchSize eigenschap ingesteld op 10. Wanneer de bewerking de ongeldige rij tegenkomt, wordt er een uitzondering gegenereerd. In dit eerste voorbeeld wordt de bulksgewijze kopieerbewerking niet uitgevoerd. Alle batches die tot het punt van de fout zijn gekopieerd, worden doorgevoerd; de batch met de dubbele sleutel wordt teruggedraaid en de bulkkopiebewerking wordt gestopt voordat andere batches worden verwerkt.

Notitie

Dit voorbeeld wordt alleen uitgevoerd als u de werktabellen hebt gemaakt, zoals beschreven in voorbeeldinstallatie voor bulksgewijs kopiëren. Deze code wordt verstrekt om alleen de syntaxis voor het gebruik van SqlBulkCopy te demonstreren. Als de bron- en doeltabellen zich in hetzelfde SQL Server-exemplaar bevinden, is het eenvoudiger en sneller om een Transact-SQL-instructieINSERT … SELECT te gebruiken om de gegevens te kopiëren.

var connectionString = GetConnectionString();
// Open a sourceConnection to the AdventureWorks database.
using (SqlConnection sourceConnection =
           new(connectionString))
{
    sourceConnection.Open();

    //  Delete all from the destination table.
    SqlCommand commandDelete = new()
    {
        Connection = sourceConnection,
        CommandText =
        "DELETE FROM dbo.BulkCopyDemoMatchingColumns"
    };
    commandDelete.ExecuteNonQuery();

    //  Add a single row that will result in duplicate key
    //  when all rows from source are bulk copied.
    //  Note that this technique will only be successful in
    //  illustrating the point if a row with ProductID = 446
    //  exists in the AdventureWorks Production.Products table.
    //  If you have made changes to the data in this table, change
    //  the SQL statement in the code to add a ProductID that
    //  does exist in your version of the Production.Products
    //  table. Choose any ProductID in the middle of the table
    //  (not first or last row) to best illustrate the result.
    SqlCommand commandInsert = new()
    {
        Connection = sourceConnection,
        CommandText =
        "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns ON;" +
        "INSERT INTO " + "dbo.BulkCopyDemoMatchingColumns " +
        "([ProductID], [Name] ,[ProductNumber]) " +
        "VALUES(446, 'Lock Nut 23','LN-3416');" +
        "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns OFF"
    };
    commandInsert.ExecuteNonQuery();

    // Perform an initial count on the destination table.
    SqlCommand commandRowCount = new(
        "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;",
        sourceConnection);
    long countStart = Convert.ToInt32(
        commandRowCount.ExecuteScalar());
    Console.WriteLine("Starting row count = {0}", countStart);

    //  Get data from the source table as a SqlDataReader.
    SqlCommand commandSourceData = new(
        "SELECT ProductID, Name, ProductNumber " +
        "FROM Production.Product;", sourceConnection);
    SqlDataReader reader = commandSourceData.ExecuteReader();

    // Set up the bulk copy object using the KeepIdentity option.
    using (SqlBulkCopy bulkCopy = new(
               connectionString, SqlBulkCopyOptions.KeepIdentity))
    {
        bulkCopy.BatchSize = 10;
        bulkCopy.DestinationTableName =
            "dbo.BulkCopyDemoMatchingColumns";

        // Write from the source to the destination.
        // This should fail with a duplicate key error
        // after some of the batches have been copied.
        try
        {
            bulkCopy.WriteToServer(reader);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            reader.Close();
        }
    }

    // Perform a final count on the destination
    // table to see how many rows were added.
    long countEnd = Convert.ToInt32(
        commandRowCount.ExecuteScalar());
    Console.WriteLine("Ending row count = {0}", countEnd);
    Console.WriteLine("{0} rows were added.", countEnd - countStart);
    Console.WriteLine("Press Enter to finish.");
    Console.ReadLine();
}
Imports System.Data.SqlClient

Module Module1
    Sub Main()
        Dim connectionString As String = GetConnectionString()

        ' Open a sourceConnection to the AdventureWorks database.
        Using sourceConnection As SqlConnection = _
           New SqlConnection(connectionString)
            sourceConnection.Open()

            ' Delete all from the destination table.
            Dim commandDelete As New SqlCommand
            commandDelete.Connection = sourceConnection
            commandDelete.CommandText = _
               "DELETE FROM dbo.BulkCopyDemoMatchingColumns"
            commandDelete.ExecuteNonQuery()

            ' Add a single row that will result in duplicate key
            ' when all rows from source are bulk copied.
            ' Note that this technique will only be successful in
            ' illustrating the point if a row with ProductID = 446
            ' exists in the AdventureWorks Production.Products table.
            ' If you have made changes to the data in this table, change
            ' the SQL statement in the code to add a ProductID that
            ' does exist in your version of the Production.Products
            ' table. Choose any ProductID in the middle of the table
            ' (not first or last row) to best illustrate the result.
            Dim commandInsert As New SqlCommand
            commandInsert.Connection = sourceConnection
            commandInsert.CommandText = _
               "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns ON;" & _
               "INSERT INTO dbo.BulkCopyDemoMatchingColumns " & _
               "([ProductID], [Name] ,[ProductNumber]) " & _
               "VALUES(446, 'Lock Nut 23','LN-3416');" & _
               "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns OFF"
            commandInsert.ExecuteNonQuery()

            ' Perform an initial count on the destination table.
            Dim commandRowCount As New SqlCommand( _
               "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
                sourceConnection)
            Dim countStart As Long = _
               System.Convert.ToInt32(commandRowCount.ExecuteScalar())
            Console.WriteLine("Starting row count = {0}", countStart)

            ' Get data from the source table as a SqlDataReader.
            Dim commandSourceData As SqlCommand = New SqlCommand( _
               "SELECT ProductID, Name, ProductNumber " & _
               "FROM Production.Product;", sourceConnection)
            Dim reader As SqlDataReader = _
             commandSourceData.ExecuteReader()

            ' Set up the bulk copy object using the KeepIdentity option.
            Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(connectionString, _
              SqlBulkCopyOptions.KeepIdentity)
                bulkCopy.BatchSize = 10
                bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"

                ' Write from the source to the destination.
                ' This should fail with a duplicate key error
                ' after some of the batches have already been copied.
                Try
                    bulkCopy.WriteToServer(reader)

                Catch ex As Exception
                    Console.WriteLine(ex.Message)

                Finally
                    reader.Close()
                End Try
            End Using

            ' Perform a final count on the destination table
            ' to see how many rows were added.
            Dim countEnd As Long = _
                System.Convert.ToInt32(commandRowCount.ExecuteScalar())
            Console.WriteLine("Ending row count = {0}", countEnd)
            Console.WriteLine("{0} rows were added.", countEnd - countStart)
            Console.WriteLine("Press Enter to finish.")
            Console.ReadLine()
        End Using
    End Sub

    Private Function GetConnectionString() As String
        Throw New NotImplementedException()
    End Function
End Module

Een toegewezen bulkkopiebewerking uitvoeren in een transactie

Standaard is een bulkkopiebewerking een eigen transactie. Wanneer u een speciale bulkkopiebewerking wilt uitvoeren, maakt u een nieuw exemplaar van SqlBulkCopy met een verbindingsreeks of gebruikt u een bestaand SqlConnection object zonder een actieve transactie. In elk scenario wordt de bulkkopiebewerking gemaakt en vervolgens de transactie doorgevoerd of teruggedraaid.

U kunt de optie in de SqlBulkCopy klasseconstructor expliciet opgeven UseInternalTransaction om expliciet een bulkkopiebewerking uit te voeren in een eigen transactie, waardoor elke batch van de bulkkopiebewerking binnen een afzonderlijke transactie wordt uitgevoerd.

Notitie

Aangezien verschillende batches in verschillende transacties worden uitgevoerd, blijft de database behouden als er een fout optreedt tijdens de bulkkopiebewerking, alle rijen in de huidige batch teruggedraaid, maar rijen uit vorige batches blijven in de database.

De volgende consoletoepassing is vergelijkbaar met het vorige voorbeeld, met één uitzondering: In dit voorbeeld beheert de bulkkopiebewerking zijn eigen transacties. Alle batches die tot het punt van de fout zijn gekopieerd, worden doorgevoerd; de batch met de dubbele sleutel wordt teruggedraaid en de bulkkopiebewerking wordt gestopt voordat andere batches worden verwerkt.

Belangrijk

Dit voorbeeld wordt alleen uitgevoerd als u de werktabellen hebt gemaakt, zoals beschreven in voorbeeldinstallatie voor bulksgewijs kopiëren. Deze code wordt verstrekt om alleen de syntaxis voor het gebruik van SqlBulkCopy te demonstreren. Als de bron- en doeltabellen zich in hetzelfde SQL Server-exemplaar bevinden, is het eenvoudiger en sneller om een Transact-SQL-instructieINSERT … SELECT te gebruiken om de gegevens te kopiëren.

var connectionString = GetConnectionString();
// Open a sourceConnection to the AdventureWorks database.
using (SqlConnection sourceConnection =
           new(connectionString))
{
    sourceConnection.Open();

    //  Delete all from the destination table.
    SqlCommand commandDelete = new()
    {
        Connection = sourceConnection,
        CommandText =
        "DELETE FROM dbo.BulkCopyDemoMatchingColumns"
    };
    commandDelete.ExecuteNonQuery();

    //  Add a single row that will result in duplicate key
    //  when all rows from source are bulk copied.
    //  Note that this technique will only be successful in
    //  illustrating the point if a row with ProductID = 446
    //  exists in the AdventureWorks Production.Products table.
    //  If you have made changes to the data in this table, change
    //  the SQL statement in the code to add a ProductID that
    //  does exist in your version of the Production.Products
    //  table. Choose any ProductID in the middle of the table
    //  (not first or last row) to best illustrate the result.
    SqlCommand commandInsert = new()
    {
        Connection = sourceConnection,
        CommandText =
        "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns ON;" +
        "INSERT INTO " + "dbo.BulkCopyDemoMatchingColumns " +
        "([ProductID], [Name] ,[ProductNumber]) " +
        "VALUES(446, 'Lock Nut 23','LN-3416');" +
        "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns OFF"
    };
    commandInsert.ExecuteNonQuery();

    // Perform an initial count on the destination table.
    SqlCommand commandRowCount = new(
        "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;",
        sourceConnection);
    long countStart = Convert.ToInt32(
        commandRowCount.ExecuteScalar());
    Console.WriteLine("Starting row count = {0}", countStart);

    //  Get data from the source table as a SqlDataReader.
    SqlCommand commandSourceData = new(
        "SELECT ProductID, Name, ProductNumber " +
        "FROM Production.Product;", sourceConnection);
    SqlDataReader reader = commandSourceData.ExecuteReader();

    // Set up the bulk copy object.
    // Note that when specifying the UseInternalTransaction
    // option, you cannot also specify an external transaction.
    // Therefore, you must use the SqlBulkCopy construct that
    // requires a string for the connection, rather than an
    // existing SqlConnection object.
    using (SqlBulkCopy bulkCopy = new(
               connectionString, SqlBulkCopyOptions.KeepIdentity |
               SqlBulkCopyOptions.UseInternalTransaction))
    {
        bulkCopy.BatchSize = 10;
        bulkCopy.DestinationTableName =
            "dbo.BulkCopyDemoMatchingColumns";

        // Write from the source to the destination.
        // This should fail with a duplicate key error
        // after some of the batches have been copied.
        try
        {
            bulkCopy.WriteToServer(reader);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            reader.Close();
        }
    }

    // Perform a final count on the destination
    // table to see how many rows were added.
    long countEnd = Convert.ToInt32(
        commandRowCount.ExecuteScalar());
    Console.WriteLine("Ending row count = {0}", countEnd);
    Console.WriteLine("{0} rows were added.", countEnd - countStart);
    Console.WriteLine("Press Enter to finish.");
    Console.ReadLine();
}
Imports System.Data.SqlClient

Module Module1
    Sub Main()
        Dim connectionString As String = GetConnectionString()

        ' Open a sourceConnection to the AdventureWorks database.
        Using sourceConnection As SqlConnection = _
           New SqlConnection(connectionString)
            sourceConnection.Open()

            ' Delete all from the destination table.
            Dim commandDelete As New SqlCommand
            commandDelete.Connection = sourceConnection
            commandDelete.CommandText = _
               "DELETE FROM dbo.BulkCopyDemoMatchingColumns"
            commandDelete.ExecuteNonQuery()

            ' Add a single row that will result in duplicate key
            ' when all rows from source are bulk copied.
            ' Note that this technique will only be successful in
            ' illustrating the point if a row with ProductID = 446
            ' exists in the AdventureWorks Production.Products table.
            ' If you have made changes to the data in this table, change
            ' the SQL statement in the code to add a ProductID that
            ' does exist in your version of the Production.Products
            ' table. Choose any ProductID in the middle of the table
            ' (not first or last row) to best illustrate the result.
            Dim commandInsert As New SqlCommand
            commandInsert.Connection = sourceConnection
            commandInsert.CommandText = _
               "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns ON;" & _
               "INSERT INTO dbo.BulkCopyDemoMatchingColumns " & _
               "([ProductID], [Name] ,[ProductNumber]) " & _
               "VALUES(446, 'Lock Nut 23','LN-3416');" & _
               "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns OFF"
            commandInsert.ExecuteNonQuery()

            ' Perform an initial count on the destination table.
            Dim commandRowCount As New SqlCommand( _
               "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
                sourceConnection)
            Dim countStart As Long = _
               System.Convert.ToInt32(commandRowCount.ExecuteScalar())
            Console.WriteLine("Starting row count = {0}", countStart)

            ' Get data from the source table as a SqlDataReader.
            Dim commandSourceData As SqlCommand = New SqlCommand( _
               "SELECT ProductID, Name, ProductNumber " & _
               "FROM Production.Product;", sourceConnection)
            Dim reader As SqlDataReader = _
             commandSourceData.ExecuteReader()

            ' Set up the bulk copy object.
            ' Note that when specifying the UseInternalTransaction option,
            ' you cannot also specify an external transaction. Therefore,
            ' you must use the SqlBulkCopy construct that requires a string
            ' for the connection, rather than an existing SqlConnection object.
            Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(connectionString, _
             SqlBulkCopyOptions.UseInternalTransaction Or _
             SqlBulkCopyOptions.KeepIdentity)
                bulkCopy.BatchSize = 10
                bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"

                ' Write from the source to the destination.
                ' This should fail with a duplicate key error
                ' after some of the batches have already been copied.
                Try
                    bulkCopy.WriteToServer(reader)

                Catch ex As Exception
                    Console.WriteLine(ex.Message)

                Finally
                    reader.Close()
                End Try
            End Using

            ' Perform a final count on the destination table
            ' to see how many rows were added.
            Dim countEnd As Long = _
                System.Convert.ToInt32(commandRowCount.ExecuteScalar())
            Console.WriteLine("Ending row count = {0}", countEnd)
            Console.WriteLine("{0} rows were added.", countEnd - countStart)
            Console.WriteLine("Press Enter to finish.")
            Console.ReadLine()
        End Using
    End Sub

    Private Function GetConnectionString() As String
        Throw New NotImplementedException()
    End Function
End Module

Bestaande transacties gebruiken

U kunt een bestaand SqlTransaction object opgeven als parameter in een SqlBulkCopy constructor. In dit geval wordt de bulksgewijze kopieerbewerking uitgevoerd in een bestaande transactie en wordt er geen wijziging aangebracht in de transactiestatus (dat wil gezegd: deze wordt niet doorgevoerd of afgebroken). Hierdoor kan een toepassing de bulksgewijze kopieerbewerking opnemen in een transactie met andere databasebewerkingen. Als u echter geen object opgeeft SqlTransaction en een null-verwijzing doorgeeft en de verbinding een actieve transactie heeft, wordt er een uitzondering gegenereerd.

Als u de volledige bulkkopiebewerking wilt terugdraaien omdat er een fout optreedt of als de bulkkopie moet worden uitgevoerd als onderdeel van een groter proces dat kan worden teruggedraaid, kunt u een SqlTransaction object aan de SqlBulkCopy constructor opgeven.

De volgende consoletoepassing is vergelijkbaar met het eerste voorbeeld (niet-transacted), met één uitzondering: in dit voorbeeld is de bulkkopiebewerking opgenomen in een grotere, externe transactie. Wanneer de fout bij schending van de primaire sleutel optreedt, wordt de hele transactie teruggedraaid en worden er geen rijen toegevoegd aan de doeltabel.

Belangrijk

Dit voorbeeld wordt alleen uitgevoerd als u de werktabellen hebt gemaakt, zoals beschreven in voorbeeldinstallatie voor bulksgewijs kopiëren. Deze code wordt verstrekt om alleen de syntaxis voor het gebruik van SqlBulkCopy te demonstreren. Als de bron- en doeltabellen zich in hetzelfde SQL Server-exemplaar bevinden, is het eenvoudiger en sneller om een Transact-SQL-instructieINSERT … SELECT te gebruiken om de gegevens te kopiëren.

var connectionString = GetConnectionString();
// Open a sourceConnection to the AdventureWorks database.
using (SqlConnection sourceConnection =
           new(connectionString))
{
    sourceConnection.Open();

    //  Delete all from the destination table.
    SqlCommand commandDelete = new()
    {
        Connection = sourceConnection,
        CommandText =
        "DELETE FROM dbo.BulkCopyDemoMatchingColumns"
    };
    commandDelete.ExecuteNonQuery();

    //  Add a single row that will result in duplicate key
    //  when all rows from source are bulk copied.
    //  Note that this technique will only be successful in
    //  illustrating the point if a row with ProductID = 446
    //  exists in the AdventureWorks Production.Products table.
    //  If you have made changes to the data in this table, change
    //  the SQL statement in the code to add a ProductID that
    //  does exist in your version of the Production.Products
    //  table. Choose any ProductID in the middle of the table
    //  (not first or last row) to best illustrate the result.
    SqlCommand commandInsert = new()
    {
        Connection = sourceConnection,
        CommandText =
        "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns ON;" +
        "INSERT INTO " + "dbo.BulkCopyDemoMatchingColumns " +
        "([ProductID], [Name] ,[ProductNumber]) " +
        "VALUES(446, 'Lock Nut 23','LN-3416');" +
        "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns OFF"
    };
    commandInsert.ExecuteNonQuery();

    // Perform an initial count on the destination table.
    SqlCommand commandRowCount = new(
        "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;",
        sourceConnection);
    long countStart = Convert.ToInt32(
        commandRowCount.ExecuteScalar());
    Console.WriteLine("Starting row count = {0}", countStart);

    //  Get data from the source table as a SqlDataReader.
    SqlCommand commandSourceData = new(
        "SELECT ProductID, Name, ProductNumber " +
        "FROM Production.Product;", sourceConnection);
    SqlDataReader reader = commandSourceData.ExecuteReader();

    //Set up the bulk copy object inside the transaction.
    using (SqlConnection destinationConnection =
               new(connectionString))
    {
        destinationConnection.Open();

        using (SqlTransaction transaction =
                   destinationConnection.BeginTransaction())
        {
            using (SqlBulkCopy bulkCopy = new(
                       destinationConnection, SqlBulkCopyOptions.KeepIdentity,
                       transaction))
            {
                bulkCopy.BatchSize = 10;
                bulkCopy.DestinationTableName =
                    "dbo.BulkCopyDemoMatchingColumns";

                // Write from the source to the destination.
                // This should fail with a duplicate key error.
                try
                {
                    bulkCopy.WriteToServer(reader);
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    transaction.Rollback();
                }
                finally
                {
                    reader.Close();
                }
            }
        }
    }

    // Perform a final count on the destination
    // table to see how many rows were added.
    long countEnd = Convert.ToInt32(
        commandRowCount.ExecuteScalar());
    Console.WriteLine("Ending row count = {0}", countEnd);
    Console.WriteLine("{0} rows were added.", countEnd - countStart);
    Console.WriteLine("Press Enter to finish.");
    Console.ReadLine();
}
Imports System.Data.SqlClient

Module Module1
    Sub Main()
        Dim connectionString As String = GetConnectionString()

        ' Open a sourceConnection to the AdventureWorks database.
        Using sourceConnection As SqlConnection = _
           New SqlConnection(connectionString)
            sourceConnection.Open()

            ' Delete all from the destination table.
            Dim commandDelete As New SqlCommand
            commandDelete.Connection = sourceConnection
            commandDelete.CommandText = _
               "DELETE FROM dbo.BulkCopyDemoMatchingColumns"
            commandDelete.ExecuteNonQuery()

            ' Add a single row that will result in duplicate key
            ' when all rows from source are bulk copied.
            ' Note that this technique will only be successful in
            ' illustrating the point if a row with ProductID = 446
            ' exists in the AdventureWorks Production.Products table.
            ' If you have made changes to the data in this table, change
            ' the SQL statement in the code to add a ProductID that
            ' does exist in your version of the Production.Products
            ' table. Choose any ProductID in the middle of the table
            ' (not first or last row) to best illustrate the result.
            Dim commandInsert As New SqlCommand
            commandInsert.Connection = sourceConnection
            commandInsert.CommandText = _
               "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns ON;" & _
               "INSERT INTO dbo.BulkCopyDemoMatchingColumns " & _
               "([ProductID], [Name] ,[ProductNumber]) " & _
               "VALUES(446, 'Lock Nut 23','LN-3416');" & _
               "SET IDENTITY_INSERT dbo.BulkCopyDemoMatchingColumns OFF"
            commandInsert.ExecuteNonQuery()

            ' Perform an initial count on the destination table.
            Dim commandRowCount As New SqlCommand( _
               "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
                sourceConnection)
            Dim countStart As Long = _
               System.Convert.ToInt32(commandRowCount.ExecuteScalar())
            Console.WriteLine("Starting row count = {0}", countStart)

            ' Get data from the source table as a SqlDataReader.
            Dim commandSourceData As SqlCommand = New SqlCommand( _
               "SELECT ProductID, Name, ProductNumber " & _
               "FROM Production.Product;", sourceConnection)
            Dim reader As SqlDataReader = _
             commandSourceData.ExecuteReader()

            ' Set up the bulk copy object inside the transaction.
            Using destinationConnection As SqlConnection = _
               New SqlConnection(connectionString)
                destinationConnection.Open()

                Using transaction As SqlTransaction = _
                  destinationConnection.BeginTransaction()

                    Using bulkCopy As SqlBulkCopy = New _
                      SqlBulkCopy(destinationConnection, _
                         SqlBulkCopyOptions.KeepIdentity, transaction)
                        bulkCopy.BatchSize = 10
                        bulkCopy.DestinationTableName = _
                         "dbo.BulkCopyDemoMatchingColumns"

                        ' Write from the source to the destination.
                        ' This should fail with a duplicate key error.
                        Try
                            bulkCopy.WriteToServer(reader)
                            transaction.Commit()

                        Catch ex As Exception
                            Console.WriteLine(ex.Message)
                            transaction.Rollback()

                        Finally
                            reader.Close()
                        End Try
                    End Using
                End Using
            End Using

            ' Perform a final count on the destination table
            ' to see how many rows were added.
            Dim countEnd As Long = _
                System.Convert.ToInt32(commandRowCount.ExecuteScalar())
            Console.WriteLine("Ending row count = {0}", countEnd)
            Console.WriteLine("{0} rows were added.", countEnd - countStart)
            Console.WriteLine("Press Enter to finish.")
            Console.ReadLine()
        End Using
    End Sub

    Private Function GetConnectionString() As String
        Throw New NotImplementedException()
    End Function
End Module

Zie ook