Udostępnij za pośrednictwem


Transakcja i operacje kopiowania zbiorczego

Operacje kopiowania zbiorczego można wykonywać jako operacje izolowane lub w ramach transakcji wielokrotnego kroku. Ta ostatnia opcja umożliwia wykonywanie więcej niż jednej operacji kopiowania zbiorczego w ramach tej samej transakcji, a także wykonywanie innych operacji bazy danych (takich jak operacje wstawiania, aktualizacji i usuwania) przy jednoczesnym zachowaniu możliwości zatwierdzenia lub wycofania całej transakcji.

Domyślnie operacja kopiowania zbiorczego jest wykonywana jako izolowana operacja. Operacja kopiowania zbiorczego odbywa się w sposób niezwiązany z brakiem możliwości wycofywania. Jeśli musisz wycofać całą lub część kopii zbiorczej w przypadku wystąpienia błędu, możesz użyć transakcji zarządzanej SqlBulkCopy, wykonać operację kopiowania zbiorczego w ramach istniejącej transakcji lub zarejestrować się w pliku System.TransactionsTransaction.

Wykonywanie operacji kopiowania zbiorczego bez transakcji

W poniższej aplikacji konsolowej pokazano, co się stanie, gdy operacja kopiowania zbiorczego bez transakcji napotka błąd podczas operacji.

W tym przykładzie tabela źródłowa i tabela docelowa zawierają kolumnę Identity o nazwie ProductID. Kod najpierw przygotowuje tabelę docelową, usuwając wszystkie wiersze, a następnie wstawiając pojedynczy wiersz, którego identyfikator ProductID jest znany jako istniejący w tabeli źródłowej. Domyślnie nowa wartość kolumny Identity jest generowana w tabeli docelowej dla każdego dodanego wiersza. W tym przykładzie opcja jest ustawiana po otwarciu połączenia, które wymusza proces ładowania zbiorczego na użycie Identity wartości z tabeli źródłowej.

Operacja kopiowania zbiorczego jest wykonywana z właściwością ustawioną BatchSize na 10. Gdy operacja napotka nieprawidłowy wiersz, zostanie zgłoszony wyjątek. W tym pierwszym przykładzie operacja kopiowania zbiorczego nie jest transaktoryzowana. Wszystkie partie skopiowane do punktu błędu są zatwierdzane; partia zawierająca zduplikowany klucz zostanie wycofana, a operacja kopiowania zbiorczego zostanie zatrzymana przed przetworzeniem innych partii.

Uwaga

Ten przykład nie zostanie uruchomiony, chyba że zostały utworzone tabele robocze zgodnie z opisem w sekcji Konfiguracja przykładu kopiowania zbiorczego. Ten kod jest dostarczany w celu zademonstrowania składni tylko przy użyciu narzędzia SqlBulkCopy . Jeśli tabele źródłowe i docelowe znajdują się w tym samym wystąpieniu programu SQL Server, łatwiej i szybciej jest użyć instrukcji Języka Transact-SQLINSERT … SELECT do skopiowania danych.

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

Wykonywanie dedykowanej operacji kopiowania zbiorczego w transakcji

Domyślnie operacja kopiowania zbiorczego jest własną transakcją. Jeśli chcesz wykonać dedykowaną operację kopiowania zbiorczego, utwórz nowe wystąpienie SqlBulkCopy z parametry połączenia lub użyj istniejącego SqlConnection obiektu bez aktywnej transakcji. W każdym scenariuszu tworzona jest operacja kopiowania zbiorczego, a następnie zatwierdza lub cofa transakcję.

Można jawnie określić UseInternalTransaction opcję w konstruktorze SqlBulkCopy klasy, aby jawnie spowodować wykonanie operacji kopiowania zbiorczego we własnej transakcji, powodując wykonanie każdej partii operacji kopiowania zbiorczego w ramach oddzielnej transakcji.

Uwaga

Ponieważ różne partie są wykonywane w różnych transakcjach, jeśli wystąpi błąd podczas operacji kopiowania zbiorczego, wszystkie wiersze w bieżącej partii zostaną wycofane, ale wiersze z poprzednich partii pozostaną w bazie danych.

Następująca aplikacja konsolowa jest podobna do poprzedniego przykładu z jednym wyjątkiem: W tym przykładzie operacja kopiowania zbiorczego zarządza własnymi transakcjami. Wszystkie partie skopiowane do punktu błędu są zatwierdzane; partia zawierająca zduplikowany klucz zostanie wycofana, a operacja kopiowania zbiorczego zostanie zatrzymana przed przetworzeniem innych partii.

Ważne

Ten przykład nie zostanie uruchomiony, chyba że zostały utworzone tabele robocze zgodnie z opisem w sekcji Konfiguracja przykładu kopiowania zbiorczego. Ten kod jest dostarczany w celu zademonstrowania składni tylko przy użyciu narzędzia SqlBulkCopy . Jeśli tabele źródłowe i docelowe znajdują się w tym samym wystąpieniu programu SQL Server, łatwiej i szybciej jest użyć instrukcji Języka Transact-SQLINSERT … SELECT do skopiowania danych.

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

Korzystanie z istniejących transakcji

Istniejący SqlTransaction obiekt można określić jako parametr w konstruktorze SqlBulkCopy . W takiej sytuacji operacja kopiowania zbiorczego jest wykonywana w istniejącej transakcji i nie jest wprowadzana żadna zmiana stanu transakcji (oznacza to, że nie jest ani zatwierdzona, ani przerwana). Dzięki temu aplikacja może uwzględnić operację kopiowania zbiorczego w transakcji z innymi operacjami bazy danych. Jeśli jednak nie określisz SqlTransaction obiektu i przekażesz odwołanie o wartości null, a połączenie ma aktywną transakcję, zostanie zgłoszony wyjątek.

Jeśli musisz wycofać całą operację kopiowania zbiorczego, ponieważ wystąpi błąd lub jeśli kopia zbiorcza powinna zostać wykonana w ramach większego procesu, który można wycofać, możesz podać SqlTransaction obiekt konstruktorowi SqlBulkCopy .

Następująca aplikacja konsolowa jest podobna do pierwszej (niezwiązanej z transakcjami), z jednym wyjątkiem: w tym przykładzie operacja kopiowania zbiorczego jest uwzględniana w większej transakcji zewnętrznej. Gdy wystąpi błąd naruszenia klucza podstawowego, cała transakcja zostanie wycofana i do tabeli docelowej nie zostaną dodane żadne wiersze.

Ważne

Ten przykład nie zostanie uruchomiony, chyba że zostały utworzone tabele robocze zgodnie z opisem w sekcji Konfiguracja przykładu kopiowania zbiorczego. Ten kod jest dostarczany w celu zademonstrowania składni tylko przy użyciu narzędzia SqlBulkCopy . Jeśli tabele źródłowe i docelowe znajdują się w tym samym wystąpieniu programu SQL Server, łatwiej i szybciej jest użyć instrukcji Języka Transact-SQLINSERT … SELECT do skopiowania danych.

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

Zobacz też