Aracılığıyla paylaş


DataAdapters ile veri kaynaklarını güncelleştirme

Update yönteminin DataAdapter, DataSet'den veri kaynağına yapılan değişiklikleri çözmek için çağrıldığı söylenir. Update yöntemi, Fill yöntemi gibi, bağımsız değişken olarak bir DataSet örneğini ve isteğe bağlı olarak bir DataTable nesnesini veya DataTable adını alır. Örnek DataSet , yapılan değişiklikleri içeren örnektir DataSet ve DataTable değişikliklerin alındığı tabloyu tanımlar. Eğer DataTable belirtilmezse, DataTable öğesindeki ilk DataSet kullanılır.

yöntemini çağırdığınızda Update , DataAdapter yöntemi yapılan değişiklikleri analiz eder ve uygun komutu yürütür (INSERT, UPDATE veya DELETE). DataAdapter bir değişiklikle karşılaştığında, değişikliği işlemek için DataRow, InsertCommand veya UpdateCommand kullanır. Bu, ADO.NET uygulamanızın performansını en üst düzeye çıkarmak için tasarım zamanında ve mümkün olduğunda saklı yordamlar kullanarak komut söz dizimini belirtmenizi sağlar. komutunu çağırmadan Updateönce komutları açıkça ayarlamanız gerekir. Eğer Update çağrılırsa ve belirli bir güncelleştirme için uygun komut yoksa (örneğin, silinen satırlar için DeleteCommand eksikse), bir özel durum fırlatılır.

Not

SQL Server saklı yordamlarını kullanarak DataAdapter ile verileri düzenlemek veya silmek istiyorsanız, saklı yordam tanımında SET NOCOUNT ON ifadesini kullanmadığınızdan emin olun. Bu, etkilenen satır sayısının sıfır olarak geri dönmesine neden olur, ve DataAdapter bunu bir eşzamanlılık çakışması olarak yorumlar. Bu olayda bir DBConcurrencyException atılır.

Komut parametreleri, bir SQL deyiminin giriş ve çıkış değerlerini belirtmek veya bir DataSet içindeki her değiştirilen satır için saklı yordam belirlemek için kullanılabilir. Daha fazla bilgi için bkz . DataAdapter Parametreleri.

Not

DataTable tablosunda bir satırı silmek ile satırı kaldırmak arasındaki farkı anlamak önemlidir. Remove veya RemoveAt yöntemini çağırdığınızda, satır hemen kaldırılır. Arka uç veri kaynağındaki karşılık gelen satırlar, DataTable veya DataSet bir DataAdapter'ye geçirip Update çağrısı yaparsanız etkilenmez. Delete yöntemini kullandığınızda, satır DataTable içinde kalır ve silinmek üzere işaretlenir. Eğer DataTable ile DataSet'i bir DataAdapter'ye geçirir ve Update'ü çağırırsanız, arka uç veri kaynağındaki karşılık gelen satır silinir.

Eğer DataTable, tek bir veritabanı tablosuna eşleniyorsa veya ondan oluşturuluyorsa, DbCommandBuilder nesnesinden yararlanarak DeleteCommand, InsertCommand ve UpdateCommand nesnelerini otomatik olarak DataAdapter için oluşturabilirsiniz. Daha fazla bilgi için bkz . CommandBuilders ile Komut Oluşturma.

Değerleri Bir DataSet ile Eşlemek için UpdatedRowSource Kullanma

Bir DataTable nesnesinin Update yöntemine yapılan bir çağrıdan sonra DataAdapter'ye nasıl eşleneceğini, bir UpdatedRowSource nesnesinin DbCommand özelliğini kullanarak kontrol edebilirsiniz. UpdatedRowSource özelliğini UpdateRowSource numaralandırma değerlerinden birine ayarlayarak, DataAdapter komutları tarafından döndürülen çıkış parametrelerinin DataSet içindeki değiştirilmiş satıra yok sayılıp sayılmayacağını veya uygulanıp uygulanmayacağını kontrol edebilirsiniz. Ayrıca, döndürülen ilk satırın (varsa) içindeki DataTabledeğiştirilen satıra uygulanıp uygulanmayacağını da belirtebilirsiniz.

Aşağıdaki tabloda, UpdateRowSource numaralandırmasının farklı değerleri ve bunların DataAdapter ile kullanılan bir komutun davranışını nasıl etkilediği açıklanmaktadır.

UpdatedRowSource Numaralandırması Açıklama
Both Hem çıkış parametreleri hem de döndürülen sonuç kümesinin ilk satırı içindeki DataSetdeğiştirilen satıra eşlenebilir.
FirstReturnedRecord Yalnızca döndürülen sonuç kümesinin ilk satırındaki veriler içindeki DataSetdeğiştirilen satıra eşlenebilir.
None Döndürülen sonuç kümesinin çıkış parametreleri veya satırları yoksayılır.
OutputParameters Yalnızca çıkış parametreleri DataSet ile değiştirilen satıra eşlenebilir.

Update yöntemi, veri kaynağındaki değişikliklerinizi çözer; ancak diğer istemciler son doldurduğunuzdan bu yana veri kaynağındaki DataSetverileri değiştirmiş olabilir. Verilerinizi güncellemek için DataSet, DataAdapter ve Fill yöntemlerini kullanın. Tabloya yeni satırlar eklenir ve güncelleştirilmiş bilgiler mevcut satırlara eklenir. yöntemi, Fill içindeki satırların ve DataSet tarafından döndürülen SelectCommand satırlarının birincil anahtar değerlerini inceleyerek yeni bir satır eklenip eklenmeyeceğini veya mevcut bir satırın güncellenip güncellenmeyeceğini belirler. yöntemi, Fill sonuçları tarafından döndürülen bir satırdaki birincil anahtar değerine uyan bir DataSet satırı için birincil anahtar değerine rastlarsa, mevcut satırı SelectCommand tarafından döndürülen satırdaki bilgilerle günceller ve mevcut satırın SelectCommand değerini RowState olarak ayarlar. SelectCommand tarafından döndürülen bir satırın, DataSet içindeki satırların birincil anahtar değerlerinden hiçbiriyle eşleşmeyen bir birincil anahtar değeri varsa, Fill yöntemi RowState değeri Unchanged olan yeni bir satır ekler.

Not

SelectCommand bir OUTER JOIN sonucunu döndürürse, DataAdapter sonucu PrimaryKeyiçin bir DataTable değer ayarlamaz. Yinelenen satırların doğru çözümlenmesini sağlamak için PrimaryKey öğesini kendiniz tanımlamanız gerekir. Daha fazla bilgi için bkz . Birincil Anahtarları Tanımlama.

yöntemini çağırırken oluşabilecek özel durumları işlemek için, Update olayını kullanarak satır güncelleştirme hataları oluştuğunda yanıt verebilirsiniz (bkz. RowUpdated), veya 'yi DataAdapter.ContinueUpdateOnError olarak ayarlayıp true çağrısından önce, güncelleştirme tamamlandığında belirli bir satırın Update özelliğine depolanan hata bilgilerini işleyebilirsiniz (bkz. RowError).

Not

AcceptChanges'nin DataSet, DataTable veya DataRow üzerinde çağrılması, bir Original için tüm DataRow değerlerinin, Current için DataRow değerleriyle üzerine yazılmasına neden olur. Satırı benzersiz olarak tanımlayan alan değerleri değiştirilmişse, değerler çağrıldıktan AcceptChangesOriginal sonra veri kaynağındaki değerlerle eşleşmez. AcceptChanges, bir DataAdapter'in Update yöntemine yapılan çağrı sırasında her satır için otomatik olarak çağrılır. Update yöntemine yapılan bir çağrı sırasında özgün değerleri koruyabilirsiniz: İlk olarak, AcceptChangesDuringUpdate özelliğini DataAdapter olarak false ayarlayarak ya da RowUpdated olayı için bir olay işleyicisi oluşturup Status özelliğini SkipCurrentRow olarak ayarlayarak. Daha fazla bilgi için bkz . DataSet İçeriğini Birleştirme ve DataAdapter Olaylarını İşleme.

Örnek

Aşağıdaki örnekler, bir UpdateCommand öğesini açıkça ayarlayarak ve DataAdapter öğesinin Update yöntemini çağırarak değiştirilen satırlarda güncellemelerin nasıl gerçekleştirileceğini göstermektedir. WHERE yan tümcesinde belirtilen parametrenin, değeri olan 'yi kullanacak şekilde UPDATE deyiminde ayarlandığına dikkat edin. Bu önemlidir çünkü Current değer değiştirilmiş olabilir ve veri kaynağındaki değerle eşleşmeyebilir. Original değeri, veri kaynağından DataTable öğesini doldurmak için kullanılan değerdir.

static void AdapterUpdate(string connectionString)
{
    using (SqlConnection connection =
               new(connectionString))
    {
        SqlDataAdapter dataAdapter = new(
          "SELECT CategoryID, CategoryName FROM Categories",
          connection)
        {
            UpdateCommand = new SqlCommand(
           "UPDATE Categories SET CategoryName = @CategoryName " +
           "WHERE CategoryID = @CategoryID", connection)
        };

        dataAdapter.UpdateCommand.Parameters.Add(
           "@CategoryName", SqlDbType.NVarChar, 15, "CategoryName");

        SqlParameter parameter = dataAdapter.UpdateCommand.Parameters.Add(
          "@CategoryID", SqlDbType.Int);
        parameter.SourceColumn = "CategoryID";
        parameter.SourceVersion = DataRowVersion.Original;

        DataTable categoryTable = new();
        dataAdapter.Fill(categoryTable);

        DataRow categoryRow = categoryTable.Rows[0];
        categoryRow["CategoryName"] = "New Beverages";

        dataAdapter.Update(categoryTable);

        Console.WriteLine("Rows after update.");
        foreach (DataRow row in categoryTable.Rows)
        {
            {
                Console.WriteLine($"{row[0]}: {row[1]}");
            }
        }
    }
}
Private Sub AdapterUpdate(ByVal connectionString As String)

    Using connection As SqlConnection = New SqlConnection( _
       connectionString)

        Dim adapter As SqlDataAdapter = New SqlDataAdapter( _
          "SELECT CategoryID, CategoryName FROM dbo.Categories", _
          connection)

        adapter.UpdateCommand = New SqlCommand( _
          "UPDATE Categories SET CategoryName = @CategoryName " & _
           "WHERE CategoryID = @CategoryID", connection)

        adapter.UpdateCommand.Parameters.Add( _
           "@CategoryName", SqlDbType.NVarChar, 15, "CategoryName")

        Dim parameter As SqlParameter = _
           adapter.UpdateCommand.Parameters.Add( _
           "@CategoryID", SqlDbType.Int)
        parameter.SourceColumn = "CategoryID"
        parameter.SourceVersion = DataRowVersion.Original

        Dim categoryTable As New DataTable
        adapter.Fill(categoryTable)

        Dim categoryRow As DataRow = categoryTable.Rows(0)
        categoryRow("CategoryName") = "New Beverages"

        adapter.Update(categoryTable)

        Console.WriteLine("Rows after update.")
        Dim row As DataRow
        For Each row In categoryTable.Rows
            Console.WriteLine("{0}: {1}", row(0), row(1))
        Next
    End Using
End Sub

Otomatik Artış Sütunları

Veri kaynağınızdaki tablolarda otomatik artan sütunlar varsa, saklı yordamın bir çıkış parametresi olarak otomatik artış değerini geri döndürüp bu değeri bir tablodaki bir sütuna eşleyerek, veya saklı yordam ya da SQL ifadesi tarafından döndürülen bir sonuç kümesinin ilk satırındaki otomatik artış değerini alarak sütunları doldurabilirsiniz. Ya da DataSet nesnesinin RowUpdated olayını kullanarak ek bir SELECT ifadesi yürütebilirsiniz. Daha fazla bilgi ve bir örnek için bkz. Kimlik veya Otomatik Sayı Değerlerini Alma işlemi.

Eklemelerin, Güncelleştirmelerin ve Silmelerin Sıralanması

Çoğu durumda, aracılığıyla DataSet yapılan değişikliklerin veri kaynağına gönderilme sırası önemlidir. Örneğin, var olan bir satır için birincil anahtar değeri güncelleştirilir ve yeni birincil anahtar değeri yabancı anahtar olarak yeni bir satır eklenirse, ekleme işleminden önce güncelleştirmeyi işlemek önemlidir.

Select'nin DataTable yöntemini kullanarak yalnızca belirli bir DataRow ile satırlara başvuran bir RowState dizisini döndürebilirsiniz. Daha sonra döndürülen DataRow diziyi Update yöntemine DataAdapter geçirerek değiştirilen satırları işleyebilirsiniz. Güncelleştirilecek satırların bir alt kümesini belirterek, eklemelerin, güncelleştirmelerin ve silmelerin işlenme sırasını denetleyebilirsiniz.

Örneğin, aşağıdaki kod önce tablonun silinen satırlarının, ardından güncelleştirilmiş satırların ve ardından eklenen satırların işlenmesini sağlar.

Dim table As DataTable = dataSet.Tables("Customers")

' First process deletes.
dataSet.Update(table.Select(Nothing, Nothing, _
  DataViewRowState.Deleted))

' Next process updates.
adapter.Update(table.Select(Nothing, Nothing, _
  DataViewRowState.ModifiedCurrent))

' Finally, process inserts.
adapter.Update(table.Select(Nothing, Nothing, _
  DataViewRowState.Added))
DataTable table = dataSet.Tables["Customers"];

// First process deletes.
adapter.Update(table.Select(null, null, DataViewRowState.Deleted));

// Next process updates.
adapter.Update(table.Select(null, null,
  DataViewRowState.ModifiedCurrent));

// Finally, process inserts.
adapter.Update(table.Select(null, null, DataViewRowState.Added));

Veri Almak ve Güncelleştirmek için DataAdapter Kullanma

Verileri almak ve güncelleştirmek için DataAdapter kullanabilirsiniz.

  • Örnek, veritabanındaki verileri kopyalamak için DataAdapter.AcceptChangesDuringFill kullanır. Özellik false olarak ayarlanırsa, tablo doldurulurken AcceptChanges çağrılmaz ve yeni eklenen satırlar eklenen satırlar olarak kabul edilir. Bu nedenle örnek, yeni satırları veritabanına eklemek için bu satırları kullanır.

  • Örneklerde, kaynak tablo ile DataTable arasındaki eşlemeyi tanımlamak için DataAdapter.TableMappings kullanılır.

  • Örnek, bağdaştırıcının DbDataReader'dan DataTable'ı nasıl doldurduğunu belirlemek için DataAdapter.FillLoadOption'ı kullanır. DataTable oluşturduğunuzda, özelliği LoadOption.Upsert veya LoadOption.PreserveChanges olarak ayarlayarak yalnızca veritabanından geçerli sürüme veya özgün sürüme veri yazabilirsiniz.

  • Örnek ayrıca toplu işlem gerçekleştirmek için DbDataAdapter.UpdateBatchSize kullanarak tabloyu güncelleştirir.

Örneği derleyip çalıştırmadan önce örnek veritabanını oluşturmanız gerekir:

USE [master]
GO

CREATE DATABASE [MySchool]

GO

USE [MySchool]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Course]([CourseID] [nvarchar](10) NOT NULL,
[Year] [smallint] NOT NULL,
[Title] [nvarchar](100) NOT NULL,
[Credits] [int] NOT NULL,
[DepartmentID] [int] NOT NULL,
 CONSTRAINT [PK_Course] PRIMARY KEY CLUSTERED
(
[CourseID] ASC,
[Year] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Department]([DepartmentID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Budget] [money] NOT NULL,
[StartDate] [datetime] NOT NULL,
[Administrator] [int] NULL,
 CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED
(
[DepartmentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

GO

INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C1045', 2012, N'Calculus', 4, 7)
INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C1061', 2012, N'Physics', 4, 1)
INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C2021', 2012, N'Composition', 3, 2)
INSERT [dbo].[Course] ([CourseID], [Year], [Title], [Credits], [DepartmentID]) VALUES (N'C2042', 2012, N'Literature', 4, 2)

SET IDENTITY_INSERT [dbo].[Department] ON

INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (1, N'Engineering', 350000.0000, CAST(0x0000999C00000000 AS DateTime), 2)
INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (2, N'English', 120000.0000, CAST(0x0000999C00000000 AS DateTime), 6)
INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (4, N'Economics', 200000.0000, CAST(0x0000999C00000000 AS DateTime), 4)
INSERT [dbo].[Department] ([DepartmentID], [Name], [Budget], [StartDate], [Administrator]) VALUES (7, N'Mathematics', 250024.0000, CAST(0x0000999C00000000 AS DateTime), 3)
SET IDENTITY_INSERT [dbo].[Department] OFF

ALTER TABLE [dbo].[Course]  WITH CHECK ADD  CONSTRAINT [FK_Course_Department] FOREIGN KEY([DepartmentID])
REFERENCES [dbo].[Department] ([DepartmentID])
GO
ALTER TABLE [dbo].[Course] CHECK CONSTRAINT [FK_Course_Department]
GO
using System;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using CSDataAdapterOperations.Properties;

namespace CSDataAdapterOperations.Properties {
   internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

      private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

      public static Settings Default {
         get {
            return defaultInstance;
         }
      }

      [global::System.Configuration.ApplicationScopedSettingAttribute()]
      public string MySchoolConnectionString {
         get {
            return ((string)(this["MySchoolConnectionString"]));
         }
      }
   }
}

class Program {
   static void Main(string[] args) {
      Settings settings = new Settings();

      // Copy the data from the database.  Get the table Department and Course from the database.
      String selectString = @"SELECT [DepartmentID],[Name],[Budget],[StartDate],[Administrator]
                                     FROM [MySchool].[dbo].[Department];

                                   SELECT [CourseID],@Year as [Year],Max([Title]) as [Title],
                                   Max([Credits]) as [Credits],Max([DepartmentID]) as [DepartmentID]
                                   FROM [MySchool].[dbo].[Course]
                                   Group by [CourseID]";

      DataSet mySchool = new DataSet();

      SqlCommand selectCommand = new SqlCommand(selectString);
      SqlParameter parameter = selectCommand.Parameters.Add("@Year", SqlDbType.SmallInt, 2);
      parameter.Value = new Random(DateTime.Now.Millisecond).Next(9999);

      // Use DataTableMapping to map the source tables and the destination tables.
      DataTableMapping[] tableMappings = {new DataTableMapping("Table", "Department"), new DataTableMapping("Table1", "Course")};
      CopyData(mySchool, settings.MySchoolConnectionString, selectCommand, tableMappings);

      Console.WriteLine("The following tables are from the database.");
      foreach (DataTable table in mySchool.Tables) {
         Console.WriteLine(table.TableName);
         ShowDataTable(table);
      }

      // Roll back the changes
      DataTable department = mySchool.Tables["Department"];
      DataTable course = mySchool.Tables["Course"];

      department.Rows[0]["Name"] = "New" + department.Rows[0][1];
      course.Rows[0]["Title"] = "New" + course.Rows[0]["Title"];
      course.Rows[0]["Credits"] = 10;

      Console.WriteLine("After we changed the tables:");
      foreach (DataTable table in mySchool.Tables) {
         Console.WriteLine(table.TableName);
         ShowDataTable(table);
      }

      department.RejectChanges();
      Console.WriteLine("After use the RejectChanges method in Department table to roll back the changes:");
      ShowDataTable(department);

      DataColumn[] primaryColumns = { course.Columns["CourseID"] };
      DataColumn[] resetColumns = { course.Columns["Title"] };
      ResetCourse(course, settings.MySchoolConnectionString, primaryColumns, resetColumns);
      Console.WriteLine("After use the ResetCourse method in Course table to roll back the changes:");
      ShowDataTable(course);

      // Batch update the table.
      String insertString = @"Insert into [MySchool].[dbo].[Course]([CourseID],[Year],[Title],
                                   [Credits],[DepartmentID])
             values (@CourseID,@Year,@Title,@Credits,@DepartmentID)";
      SqlCommand insertCommand = new SqlCommand(insertString);
      insertCommand.Parameters.Add("@CourseID", SqlDbType.NVarChar, 10, "CourseID");
      insertCommand.Parameters.Add("@Year", SqlDbType.SmallInt, 2, "Year");
      insertCommand.Parameters.Add("@Title", SqlDbType.NVarChar, 100, "Title");
      insertCommand.Parameters.Add("@Credits", SqlDbType.Int, 4, "Credits");
      insertCommand.Parameters.Add("@DepartmentID", SqlDbType.Int, 4, "DepartmentID");

      const Int32 batchSize = 10;
      BatchInsertUpdate(course, settings.MySchoolConnectionString, insertCommand, batchSize);
   }

   private static void CopyData(DataSet dataSet, String connectionString, SqlCommand selectCommand, DataTableMapping[] tableMappings) {
      using (SqlConnection connection = new SqlConnection(connectionString)) {
         selectCommand.Connection = connection;

         connection.Open();

         using (SqlDataAdapter adapter = new SqlDataAdapter(selectCommand)) {adapter.TableMappings.AddRange(tableMappings);
            // If set the AcceptChangesDuringFill as the false, AcceptChanges will not be called on a
            // DataRow after it is added to the DataTable during any of the Fill operations.
            adapter.AcceptChangesDuringFill = false;

            adapter.Fill(dataSet);
         }
      }
   }

   // Roll back only one column or several columns data of the Course table by call ResetDataTable method.
   private static void ResetCourse(DataTable table, String connectionString,
       DataColumn[] primaryColumns, DataColumn[] resetColumns) {
      table.PrimaryKey = primaryColumns;

      // Build the query string
      String primaryCols = String.Join(",", primaryColumns.Select(col => col.ColumnName));
      String resetCols = String.Join(",", resetColumns.Select(col => $"Max({col.ColumnName}) as {col.ColumnName}"));

      String selectString = $"Select {primaryCols},{resetCols} from Course Group by {primaryCols}");

      SqlCommand selectCommand = new SqlCommand(selectString);

      ResetDataTable(table, connectionString, selectCommand);
   }

   // RejectChanges will roll back all changes made to the table since it was loaded, or the last time AcceptChanges
   // was called. When you copy from the database, you can lose all the data after calling RejectChanges
   // The ResetDataTable method rolls back one or more columns of data.
   private static void ResetDataTable(DataTable table, String connectionString,
       SqlCommand selectCommand) {
      using (SqlConnection connection = new SqlConnection(connectionString)) {
         selectCommand.Connection = connection;

         connection.Open();

         using (SqlDataAdapter adapter = new SqlDataAdapter(selectCommand)) {
            // The incoming values for this row will be written to the current version of each
            // column. The original version of each column's data will not be changed.
            adapter.FillLoadOption = LoadOption.Upsert;

            adapter.Fill(table);
         }
      }
   }

   private static void BatchInsertUpdate(DataTable table, String connectionString,
       SqlCommand insertCommand, Int32 batchSize) {
      using (SqlConnection connection = new SqlConnection(connectionString)) {
         insertCommand.Connection = connection;
         // When setting UpdateBatchSize to a value other than 1, all the commands
         // associated with the SqlDataAdapter have to have their UpdatedRowSource
         // property set to None or OutputParameters. An exception is thrown otherwise.
         insertCommand.UpdatedRowSource = UpdateRowSource.None;

         connection.Open();

         using (SqlDataAdapter adapter = new SqlDataAdapter()) {
            adapter.InsertCommand = insertCommand;
            // Gets or sets the number of rows that are processed in each round-trip to the server.
            // Setting it to 1 disables batch updates, as rows are sent one at a time.
            adapter.UpdateBatchSize = batchSize;

            adapter.Update(table);

            Console.WriteLine("Successfully to update the table.");
         }
      }
   }

   private static void ShowDataTable(DataTable table) {
      foreach (DataColumn col in table.Columns) {
         Console.Write("{0,-14}", col.ColumnName);
      }
      Console.WriteLine("{0,-14}", "RowState");

      foreach (DataRow row in table.Rows) {
         foreach (DataColumn col in table.Columns) {
            if (col.DataType.Equals(typeof(DateTime)))
               Console.Write("{0,-14:d}", row[col]);
            else if (col.DataType.Equals(typeof(Decimal)))
               Console.Write("{0,-14:C}", row[col]);
            else
               Console.Write("{0,-14}", row[col]);
         }
         Console.WriteLine("{0,-14}", row.RowState);
      }
   }
}

Ayrıca bkz.