Share via


Gegevensbronnen bijwerken met DataAdapters

De Update methode van de DataAdapter taak wordt aangeroepen om wijzigingen van een DataSet back-up naar de gegevensbron op te lossen. De Update methode, zoals de Fill methode, neemt als argumenten een exemplaar van een DataSeten een optioneel object of DataTable een optionele DataTable naam. Het DataSet exemplaar bevat DataSet de wijzigingen die zijn aangebracht en de DataTable tabel waaruit de wijzigingen moeten worden opgehaald. Als er geen DataTable is opgegeven, wordt de eerste DataTable in het DataSet gebruik gebruikt.

Wanneer u de Update methode aanroept, analyseert de DataAdapter wijzigingen die zijn aangebracht en voert u de juiste opdracht uit (INSERT, UPDATE of DELETE). Wanneer er DataAdapter een wijziging optreedt in een DataRow, wordt de InsertCommand, UpdateCommandof DeleteCommand de wijziging verwerkt. Hiermee kunt u de prestaties van uw ADO.NET toepassing maximaliseren door de opdrachtsyntaxis op te geven tijdens het ontwerp en, indien mogelijk, door gebruik te maken van opgeslagen procedures. U moet de opdrachten expliciet instellen voordat u aanroept Update. Als Update deze wordt aangeroepen en de juiste opdracht niet bestaat voor een bepaalde update (bijvoorbeeld geen DeleteCommand voor verwijderde rijen), wordt er een uitzondering gegenereerd.

Notitie

Als u opgeslagen SQL Server-procedures gebruikt om gegevens te bewerken of te verwijderen met behulp van een DataAdapter, zorg er dan voor dat u SET NOCOUNT ON niet gebruikt in de definitie van de opgeslagen procedure. Dit zorgt ervoor dat het aantal geretourneerde rijen nul is, wat door de DataAdapter interpretatie als een gelijktijdigheidsconflict wordt geïnterpreteerd. In dit geval wordt er een DBConcurrencyException gegooid.

Opdrachtparameters kunnen worden gebruikt om invoer- en uitvoerwaarden op te geven voor een SQL-instructie of opgeslagen procedure voor elke gewijzigde rij in een DataSet. Zie DataAdapter Parameters voor meer informatie.

Notitie

Het is belangrijk om het verschil te begrijpen tussen het verwijderen van een rij in een DataTable rij en het verwijderen van de rij. Wanneer u de Remove of RemoveAt methode aanroept, wordt de rij onmiddellijk verwijderd. Alle bijbehorende rijen in de gegevensbron van de back-end worden niet beïnvloed als u vervolgens de DataTable of aanroep DataAdapter doorgeeft of DataSet aanroeptUpdate. Wanneer u de Delete methode gebruikt, blijft de rij in de DataTable rij staan en wordt deze gemarkeerd voor verwijdering. Als u de DataTable of DataSet aanroep DataAdapterUpdatevervolgens doorgeeft, wordt de bijbehorende rij in de back-endgegevensbron verwijderd.

Als uw DataTable toewijzingen aan of worden gegenereerd op basis van één databasetabel, kunt u profiteren van het DbCommandBuilder object om automatisch de DeleteCommand, InsertCommanden UpdateCommand objecten voor de DataAdaptertabel te genereren. Zie Opdrachten genereren met CommandBuilders voor meer informatie.

BijgewerkteRowSource gebruiken om waarden toe te wijzen aan een DataSet

U kunt bepalen hoe de waarden die worden geretourneerd uit de gegevensbron, worden toegewezen aan de DataTable volgende aanroep naar de updatemethode van een DataAdapter, met behulp van de UpdatedRowSource eigenschap van een DbCommand object. Door de UpdatedRowSource eigenschap in te stellen op een van de UpdateRowSource opsommingswaarden, kunt u bepalen of uitvoerparameters die door de DataAdapter opdrachten worden geretourneerd, worden genegeerd of toegepast op de gewijzigde rij in de DataSet. U kunt ook opgeven of de eerste geretourneerde rij (als deze bestaat) wordt toegepast op de gewijzigde rij in de DataTable.

In de volgende tabel worden de verschillende waarden van de UpdateRowSource opsomming beschreven en hoe deze van invloed zijn op het gedrag van een opdracht die wordt gebruikt met een DataAdapter.

Opsomming VanRowSource bijgewerkt Beschrijving
Both Zowel de uitvoerparameters als de eerste rij van een geretourneerde resultatenset kunnen worden toegewezen aan de gewijzigde rij in de DataSet.
FirstReturnedRecord Alleen de gegevens in de eerste rij van een geretourneerde resultatenset kunnen worden toegewezen aan de gewijzigde rij in de DataSet.
None Uitvoerparameters of rijen van een geretourneerde resultatenset worden genegeerd.
OutputParameters Alleen uitvoerparameters kunnen worden toegewezen aan de gewijzigde rij in de DataSet.

De methode lost uw wijzigingen weer op in de gegevensbron. Andere Update clients hebben mogelijk gegevens gewijzigd in de gegevensbron sinds de laatste keer dat u de DataSetgegevens hebt ingevuld. Als u uw DataSet gegevens wilt vernieuwen met de huidige gegevens, gebruikt u de DataAdapter en Fill methode. Nieuwe rijen worden toegevoegd aan de tabel en bijgewerkte informatie wordt opgenomen in bestaande rijen. De Fill methode bepaalt of een nieuwe rij wordt toegevoegd of een bestaande rij wordt bijgewerkt door de primaire-sleutelwaarden van de rijen in de DataSet rijen te onderzoeken en de rijen die worden geretourneerd door de SelectCommand. Als de Fill methode een primaire-sleutelwaarde tegenkomt voor een rij in de DataSet rij die overeenkomt met een primaire-sleutelwaarde uit een rij in de resultaten die door de SelectCommandresultaten worden geretourneerd, wordt de bestaande rij bijgewerkt met de informatie uit de rij die door de SelectCommand rij wordt geretourneerd en stelt de bestaande rij in RowState op Unchanged. Als een rij die door de SelectCommand rij wordt geretourneerd, een primaire-sleutelwaarde heeft die niet overeenkomt met een van de primaire-sleutelwaarden van de rijen in de DataSet, voegt de Fill methode een nieuwe rij toe met een RowState van Unchanged.

Notitie

Als de SelectCommand resultaten van een OUTER JOIN worden geretourneerd, wordt er DataAdapter geen waarde ingesteld PrimaryKey voor het resulterende DataTable. U moet de PrimaryKey uzelf definiëren om ervoor te zorgen dat dubbele rijen correct worden omgezet. Zie Primaire sleutels definiëren voor meer informatie.

Als u uitzonderingen wilt verwerken die kunnen optreden bij het aanroepen van de Update methode, kunt u de RowUpdated gebeurtenis gebruiken om te reageren op fouten bij het bijwerken van rijen wanneer deze optreden (zie DataAdapter-gebeurtenissen verwerken), of kunt u instellen trueDataAdapter.ContinueUpdateOnError op voordat u aanroept Updateen reageert u op de foutgegevens die zijn opgeslagen in de RowError eigenschap van een bepaalde rij wanneer de update is voltooid (zie rijfoutinformatie).

Notitie

Het aanroepen AcceptChanges van de DataSet, DataTableof DataRow zorgt ervoor dat alle Original waarden voor een DataRow worden overschreven met de waarden voor de CurrentDataRow. Als de veldwaarden die de rij identificeren als uniek zijn gewijzigd, komen de waarden na het aanroepen AcceptChanges van de Original waarden niet meer overeen met de waarden in de gegevensbron. AcceptChanges wordt automatisch aangeroepen voor elke rij tijdens een aanroep naar de updatemethode van een DataAdapter. U kunt de oorspronkelijke waarden behouden tijdens een aanroep van de updatemethode door eerst de eigenschap van de AcceptChangesDuringUpdateDataAdapter eigenschap in te stellen op onwaar of door een gebeurtenis-handler voor de RowUpdated gebeurtenis te maken en de instelling in Status te SkipCurrentRowstellen op . Zie DataSet-inhoud samenvoegen en DataAdapter-gebeurtenissen verwerken voor meer informatie.

Opmerking

In de volgende voorbeelden ziet u hoe u updates kunt uitvoeren voor gewijzigde rijen door expliciet de UpdateCommand methode van een DataAdapter en aan te roepen Update . U ziet dat de parameter die is opgegeven in de WHERE-component van de UPDATE-instructie is ingesteld op het gebruik van de Original waarde van de SourceColumn. Dit is belangrijk omdat de Current waarde mogelijk is gewijzigd en mogelijk niet overeenkomt met de waarde in de gegevensbron. De Original waarde is de waarde die is gebruikt om de DataTable gegevensbron te vullen.

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("{0}: {1}", 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

Kolommen voor automatisch maken

Als de tabellen uit uw gegevensbron automatisch incrementele kolommen bevatten, kunt u de kolommen in uw DataSet kolom vullen door de waarde voor automatisch verhogen als uitvoerparameter van een opgeslagen procedure te retourneren en deze toe te voegen aan een kolom in een tabel door de waarde voor automatisch verhogen in de eerste rij van een resultatenset te retourneren die wordt geretourneerd door een opgeslagen procedure of SQL-instructie, of door de RowUpdated gebeurtenis van de DataAdapter gebeurtenis te gebruiken om een extra SELECT-instructie uit te voeren. Zie Identiteits- of Autonummeringswaarden ophalen voor meer informatie en een voorbeeld.

Volgorde van invoegingen, updates en verwijderingen

In veel gevallen is de volgorde waarin wijzigingen die via de DataSet gegevensbron zijn aangebracht, belangrijk. Als een primaire-sleutelwaarde voor een bestaande rij bijvoorbeeld wordt bijgewerkt en er een nieuwe rij is toegevoegd met de nieuwe primaire-sleutelwaarde als refererende sleutel, is het belangrijk om de update vóór de invoegbewerking te verwerken.

U kunt de Select methode van de DataTable functie gebruiken om een DataRow matrix te retourneren die alleen verwijst naar rijen met een bepaalde RowStatewaarde. Vervolgens kunt u de geretourneerde DataRow matrix doorgeven aan de Update methode van de DataAdapter om de gewijzigde rijen te verwerken. Door een subset van rijen op te geven die moeten worden bijgewerkt, kunt u de volgorde bepalen waarin invoegingen, updates en verwijderingen worden verwerkt.

De volgende code zorgt er bijvoorbeeld voor dat de verwijderde rijen van de tabel eerst worden verwerkt, vervolgens de bijgewerkte rijen en vervolgens de ingevoegde rijen.

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));

Een DataAdapter gebruiken om gegevens op te halen en bij te werken

U kunt een DataAdapter gebruiken om de gegevens op te halen en bij te werken.

  • In het voorbeeld wordt DataAdapter.AcceptChangesDuringFill gebruikt om de gegevens in de database te klonen. Als de eigenschap is ingesteld als onwaar, wordt AcceptChanges niet aangeroepen bij het vullen van de tabel en worden de zojuist toegevoegde rijen behandeld als ingevoegde rijen. In het voorbeeld worden deze rijen dus gebruikt om de nieuwe rijen in de database in te voegen.

  • De voorbeelden maken gebruik van DataAdapter.TableMappings om de toewijzing tussen de brontabel en DataTable te definiëren.

  • In het voorbeeld wordt DataAdapter.FillLoadOption gebruikt om te bepalen hoe de adapter de DataTable van DbDataReader vult. Wanneer u een gegevenstabel maakt, kunt u alleen de gegevens schrijven van de database naar de huidige versie of de oorspronkelijke versie door de eigenschap in te stellen als LoadOption.Upsert of LoadOption.PreserveChanges.

  • In het voorbeeld wordt ook de tabel bijgewerkt met behulp van DbDataAdapter.UpdateBatchSize om batchbewerkingen uit te voeren.

Voordat u het voorbeeld compileert en uitvoert, moet u de voorbeelddatabase maken:

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()]
      [global::System.Configuration.DefaultSettingValueAttribute("Data Source=(local);Initial Catalog=MySchool;Integrated Security=True")]
      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);
      }
   }
}

Zie ook