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 DataSet
en 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 DataAdapter
Update
vervolgens 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
, InsertCommand
en UpdateCommand
objecten voor de DataAdapter
tabel 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 DataSet
gegevens 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 SelectCommand
resultaten 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 true
DataAdapter.ContinueUpdateOnError
op voordat u aanroept Update
en 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
, DataTable
of DataRow
zorgt ervoor dat alle Original
waarden voor een DataRow
worden overschreven met de waarden voor de Current
DataRow
. 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 AcceptChangesDuringUpdate
DataAdapter
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 RowState
waarde. 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()]
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);
}
}
}