Aracılığıyla paylaş


İşlem ve toplu kopyalama operasyonları

ADO.NET'i indir

Toplu kopyalama işlemleri, yalıtılmış işlemler olarak veya birden çok adımlı bir işlemin parçası olarak gerçekleştirilebilir. Bu ikinci seçenek, aynı işlem içinde birden fazla toplu kopyalama işlemi gerçekleştirmenize ve eklemeler, güncelleştirmeler ve silmeler gibi diğer veritabanı işlemlerini gerçekleştirmenize ve işlemin tamamını işlemeye veya geri almaya devam edebilmenize olanak tanır.

Varsayılan olarak, toplu kopyalama işlemi yalıtılmış bir işlem olarak gerçekleştirilir. Toplu kopyalama işlemi işlem yapılmamış bir şekilde gerçekleşir ve geri döndürme fırsatı yoktur. Hata oluştuğunda toplu kopyalamanın tamamını veya bir bölümünü geri almanız gerekiyorsa şunları yapabilirsiniz:

  • Bir SqlBulkCopy-yönetimli işlem kullanın

  • Toplu kopyalama işlemini mevcut bir işlem içinde gerçekleştirme

  • System.Transactions'eTransaction kaydol.

İşlem yapmadan toplu kopyalama işlemi gerçekleştirmek

Aşağıdaki Konsol uygulaması, işlem sırasında işlem dışı bir toplu kopyalama işlemi yarıda bir hatayla karşılaştığında ne olduğunu gösterir.

Örnekte, kaynak tablo ve hedef tablonun her birinde Identityadlı bir sütunu bulunur. Kod önce tüm satırları silip ardından ProductID kaynak tabloda olduğu bilinen tek bir satır ekleyerek hedef tabloyu hazırlar. Varsayılan olarak, eklenen her satır için hedef tabloda Identity sütunu için yeni bir değer oluşturulur. Bu örnekte, bağlantı açıldığında toplu yükleme işlemini bunun yerine kaynak tablodan Identity değerlerini kullanmaya zorlayan bir seçenek ayarlanır.

Toplu kopyalama işlemi, BatchSize özelliği 10 olarak ayarlanmış şekilde yürütülür. İşlem geçersiz satırla karşı karşıya geldiğinde bir özel durum oluşturulur. Bu ilk örnekte toplu kopyalama işlemi işlem dışıdır. Hata noktasına kadar kopyalanan tüm toplu işlemler işlenir. Yinelenen anahtarı içeren veri kümesi geri alınır ve kalan veri kümelerini tamamıyla işlemeden önce toplu kopya işlemi durdurulur.

Uyarı

Bu örnek, toplu kopyalama örneği kurulumu bölümünde açıklandığı gibi iş tablolarını oluşturmadığınız sürece çalışmaz. Bu kod, yalnızca SqlBulkCopy kullanma söz dizimini göstermek için sağlanır. Kaynak ve hedef tablolar aynı SQL Server örneğinde bulunuyorsa, verileri kopyalamak için Transact-SQL INSERT ... SELECT deyimi kullanmak daha kolay ve daha hızlıdır.

using Microsoft.Data.SqlClient;

class Program
{
    static void Main()
    {
        string connectionString = GetConnectionString();
        // Open a sourceConnection to the AdventureWorks database.
        using (SqlConnection sourceConnection =
                   new SqlConnection(connectionString))
        {
            sourceConnection.Open();

            //  Delete all from the destination table.         
            SqlCommand commandDelete = 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.         
            SqlCommand commandInsert = 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.
            SqlCommand commandRowCount = new SqlCommand(
                "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;",
                sourceConnection);
            long countStart = System.Convert.ToInt32(
                commandRowCount.ExecuteScalar());
            Console.WriteLine("Starting row count = {0}", countStart);

            //  Get data from the source table as a SqlDataReader.         
            SqlCommand commandSourceData = new SqlCommand(
                "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 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 been copied.
                try
                {
                    bulkCopy.WriteToServer(reader);
                }
                catch (Exception ex)
                {
                    // Print the number of rows processed using the 
                    // RowsCopied property.
                    Console.WriteLine("{0} rows were processed.",
                        bulkCopy.RowsCopied);
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    reader.Close();
                }
            }

            // Perform a final count on the destination 
            // table to see how many rows were added.
            // Note that for this scenario, the value will 
            // not be equal to the RowsCopied property.
            long countEnd = 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();
        }
    }

    private static string GetConnectionString()
    // To avoid storing the sourceConnection string in your code, 
    // you can retrieve it from a configuration file. 
    {
        return "Data Source=(local); " +
            " Integrated Security=true;" +
            "Initial Catalog=AdventureWorks;";
    }
}

Bir transaksiyonda özel toplu kopyalama işlemi gerçekleştirme

Varsayılan olarak, toplu kopyalama işlemi kendi transaksiyonudur. Ayrılmış bir toplu kopyalama işlemi gerçekleştirmek istediğinizde, bir bağlantı dizesiyle örneği SqlBulkCopy oluşturun veya etkin bir işlem olmadan var olan SqlConnection bir nesneyi kullanın. Toplu kopyalama işlemi her senaryoda bir işlem oluşturur ve ardından işlemi kesinleştirir veya geri alır.

UseInternalTransaction seçeneğini SqlBulkCopy sınıf oluşturucusunda açıkça belirterek bir toplu kopyalama işlemini kendi işleminde yürütmeyi sağlayabilirsiniz. İşlemin her toplu işlemi ayrı bir işlem içinde yürütülür.

Uyarı

Farklı toplu işlemler farklı işlemlerde yürütülürse, toplu kopyalama işlemi sırasında bir hata oluşursa, geçerli toplu işteki tüm satırlar geri alınır, ancak önceki toplu işlemlerdeki satırlar veritabanında kalır.

Aşağıdaki konsol uygulaması, bir özel durum dışında önceki örneğe benzer: Bu örnekte, toplu kopyalama işlemi kendi işlemlerini yönetir. Hata noktasına kadar kopyalanan tüm toplu işlemler işlenir. Yinelenen anahtarı içeren veri kümesi geri alınır ve kalan veri kümelerini tamamıyla işlemeden önce toplu kopya işlemi durdurulur.

Önemli

Bu örnek, toplu kopyalama örneği kurulumu bölümünde açıklandığı gibi iş tablolarını oluşturmadığınız sürece çalışmaz. Bu kod, yalnızca SqlBulkCopy kullanma söz dizimini göstermek için sağlanır. Kaynak ve hedef tablolar aynı SQL Server örneğinde bulunuyorsa, verileri kopyalamak için Transact-SQL INSERT ... SELECT deyimi kullanmak daha kolay ve daha hızlıdır.

using Microsoft.Data.SqlClient;

class Program
{
    static void Main()
    {
        string connectionString = GetConnectionString();
        // Open a sourceConnection to the AdventureWorks database.
        using (SqlConnection sourceConnection =
                   new SqlConnection(connectionString))
        {
            sourceConnection.Open();

            //  Delete all from the destination table.         
            SqlCommand commandDelete = 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.         
            SqlCommand commandInsert = 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.
            SqlCommand commandRowCount = new SqlCommand(
                "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;",
                sourceConnection);
            long countStart = System.Convert.ToInt32(
                commandRowCount.ExecuteScalar());
            Console.WriteLine("Starting row count = {0}", countStart);

            //  Get data from the source table as a SqlDataReader.         
            SqlCommand commandSourceData = new SqlCommand(
                "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 SqlBulkCopy(
                       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)
                {
                    // Print the number of rows processed using the 
                    // RowsCopied property.
                    Console.WriteLine("{0} rows were processed.",
                        bulkCopy.RowsCopied);
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    reader.Close();
                }
            }

            // Perform a final count on the destination 
            // table to see how many rows were added.
            // Note that for this scenario, the value will 
            // not be equal to the RowsCopied property.
            long countEnd = 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();
        }
    }

    private static string GetConnectionString()
    // To avoid storing the sourceConnection string in your code, 
    // you can retrieve it from a configuration file. 
    {
        return "Data Source=(local); " +
            " Integrated Security=true;" +
            "Initial Catalog=AdventureWorks;";
    }
}

Mevcut işlemleri kullanma

Var olan bir SqlTransaction nesnesini bir SqlBulkCopy oluşturucusunda parametre olarak belirtebilirsiniz. Bu durumda, toplu kopyalama işlemi mevcut işlemde yapılır ve işlem durumunda hiçbir değişiklik yapılmaz, işlem onaylanmaz veya iptal edilmez. Bu yöntem, bir uygulamanın toplu kopyalama işlemini diğer veritabanı işlemleriyle birlikte bir işleme eklemesine olanak tanır. Ancak, bir SqlTransaction nesnesi belirtmez ve null referans geçirirseniz, ve bağlantı aktif bir işlem durumundaysa, bir hata fırlatılır.

Bir hata oluştuğundan toplu kopyalama işleminin tamamını geri almanız gerekiyorsa veya toplu kopyalama geri alınabilecek daha büyük bir işlemin parçası olarak yürütülecekse, SqlTransaction oluşturucuya SqlBulkCopy nesnesi sağlayabilirsiniz.

Aşağıdaki konsol uygulaması ilk (işlemsiz) örneğe benzer ve tek bir özel durum vardır: bu örnekte, toplu kopyalama işlemi daha büyük bir dış işleme dahil edilmiştir. Birincil anahtar ihlali hatası oluştuğunda, tüm işlem geri alınır ve hedef tabloya satır eklenmez.

Önemli

Bu örnek, toplu kopyalama örneği kurulumu bölümünde açıklandığı gibi iş tablolarını oluşturmadığınız sürece çalışmaz. Bu kod, yalnızca SqlBulkCopy kullanma söz dizimini göstermek için sağlanır. Kaynak ve hedef tablolar aynı SQL Server örneğinde bulunuyorsa, verileri kopyalamak için Transact-SQL INSERT ... SELECT deyimi kullanmak daha kolay ve daha hızlıdır.

using Microsoft.Data.SqlClient;

class Program
{
    static void Main()
    {
        string connectionString = GetConnectionString();
        // Open a sourceConnection to the AdventureWorks database.
        using (SqlConnection sourceConnection =
                   new SqlConnection(connectionString))
        {
            sourceConnection.Open();

            //  Delete all from the destination table.         
            SqlCommand commandDelete = 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.         
            SqlCommand commandInsert = 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.
            SqlCommand commandRowCount = new SqlCommand(
                "SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;",
                sourceConnection);
            long countStart = System.Convert.ToInt32(
                commandRowCount.ExecuteScalar());
            Console.WriteLine("Starting row count = {0}", countStart);

            //  Get data from the source table as a SqlDataReader.         
            SqlCommand commandSourceData = new SqlCommand(
                "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 SqlConnection(connectionString))
            {
                destinationConnection.Open();

                using (SqlTransaction transaction =
                           destinationConnection.BeginTransaction())
                {
                    using (SqlBulkCopy bulkCopy = 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 (Exception ex)
                        {
                            // Print the number of rows processed using the 
                            // RowsCopied property.
                            Console.WriteLine("{0} rows were processed.",
                                bulkCopy.RowsCopied);
                            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 = 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();
        }
    }

    private static string GetConnectionString()
    // To avoid storing the sourceConnection string in your code, 
    // you can retrieve it from a configuration file. 
    {
        return "Data Source=(local); " +
            " Integrated Security=true;" +
            "Initial Catalog=AdventureWorks;";
    }
}

Sonraki Adımlar