2 // System.Data.Common.DbDataAdapter.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Tim Coleman (tim@timcoleman.com)
7 // Sureshkumar T <tsureshkumar@novell.com>
8 // Veerapuram Varadhan <vvaradhan@novell.com>
11 // Copyright (C) Tim Coleman, 2002-2003
15 // Copyright (C) 2004, 2009 Novell, Inc (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 using System.Collections;
39 using System.ComponentModel;
41 using System.Reflection;
42 using System.Runtime.InteropServices;
44 namespace System.Data.Common
47 public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable
49 public abstract class DbDataAdapter : DataAdapter, ICloneable
54 public const string DefaultSourceTableName = "Table";
55 const string DefaultSourceColumnName = "Column";
56 CommandBehavior _behavior = CommandBehavior.Default;
59 IDbCommand _selectCommand;
60 IDbCommand _updateCommand;
61 IDbCommand _deleteCommand;
62 IDbCommand _insertCommand;
69 protected DbDataAdapter ()
73 protected DbDataAdapter (DbDataAdapter adapter) : base (adapter)
82 protected internal CommandBehavior FillCommandBehavior {
83 get { return _behavior; }
84 set { _behavior = value; }
87 IDbCommand IDbDataAdapter.SelectCommand {
88 get { return _selectCommand; }
89 set { _selectCommand = value; }
92 IDbCommand IDbDataAdapter.UpdateCommand{
93 get { return _updateCommand; }
94 set { _updateCommand = value; }
97 IDbCommand IDbDataAdapter.DeleteCommand{
98 get { return _deleteCommand; }
99 set { _deleteCommand = value; }
102 IDbCommand IDbDataAdapter.InsertCommand{
103 get { return _insertCommand; }
104 set { _insertCommand = value; }
108 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
109 public DbCommand SelectCommand {
110 get { return (DbCommand) _selectCommand; }
111 set { _selectCommand = value; }
115 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
116 public DbCommand DeleteCommand {
117 get { return (DbCommand) _deleteCommand; }
118 set { _deleteCommand = value; }
122 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
123 public DbCommand InsertCommand {
124 get { return (DbCommand)_insertCommand; }
125 set { _insertCommand = value; }
129 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
130 public DbCommand UpdateCommand {
131 get { return (DbCommand)_updateCommand; }
132 set { _updateCommand = value; }
136 public virtual int UpdateBatchSize {
140 throw new NotSupportedException ();
145 #endregion // Properties
149 #if ONLY_1_0 || ONLY_1_1
150 [DataCategory ("Fill")]
151 [DataSysDescription ("Event triggered when a recoverable error occurs during Fill.")]
152 public event FillErrorEventHandler FillError;
160 protected virtual RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
161 StatementType statementType,
162 DataTableMapping tableMapping)
164 return new RowUpdatedEventArgs (dataRow, command, statementType, tableMapping);
167 protected virtual RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
168 StatementType statementType,
169 DataTableMapping tableMapping)
171 return new RowUpdatingEventArgs (dataRow, command, statementType, tableMapping);
174 protected virtual void OnRowUpdated (RowUpdatedEventArgs value)
176 if (Events ["RowUpdated"] != null) {
177 Delegate [] rowUpdatedList = Events ["RowUpdated"].GetInvocationList ();
178 foreach (Delegate rowUpdated in rowUpdatedList) {
179 MethodInfo rowUpdatedMethod = rowUpdated.Method;
180 rowUpdatedMethod.Invoke (value, null);
185 protected virtual void OnRowUpdating (RowUpdatingEventArgs value)
187 if (Events ["RowUpdating"] != null) {
188 Delegate [] rowUpdatingList = Events ["RowUpdating"].GetInvocationList ();
189 foreach (Delegate rowUpdating in rowUpdatingList) {
190 MethodInfo rowUpdatingMethod = rowUpdating.Method;
191 rowUpdatingMethod.Invoke (value, null);
196 protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
197 StatementType statementType,
198 DataTableMapping tableMapping);
200 protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
201 StatementType statementType,
202 DataTableMapping tableMapping);
204 protected abstract void OnRowUpdated (RowUpdatedEventArgs value);
205 protected abstract void OnRowUpdating (RowUpdatingEventArgs value);
208 protected override void Dispose (bool disposing)
211 IDbDataAdapter da = (IDbDataAdapter) this;
212 if (da.SelectCommand != null) {
213 da.SelectCommand.Dispose();
214 da.SelectCommand = null;
216 if (da.InsertCommand != null) {
217 da.InsertCommand.Dispose();
218 da.InsertCommand = null;
220 if (da.UpdateCommand != null) {
221 da.UpdateCommand.Dispose();
222 da.UpdateCommand = null;
224 if (da.DeleteCommand != null) {
225 da.DeleteCommand.Dispose();
226 da.DeleteCommand = null;
231 public override int Fill (DataSet dataSet)
233 return Fill (dataSet, 0, 0, DefaultSourceTableName, ((IDbDataAdapter) this).SelectCommand, _behavior);
236 public int Fill (DataTable dataTable)
238 if (dataTable == null)
239 throw new ArgumentNullException ("DataTable");
241 return Fill (dataTable, ((IDbDataAdapter) this).SelectCommand, _behavior);
244 public int Fill (DataSet dataSet, string srcTable)
246 return Fill (dataSet, 0, 0, srcTable, ((IDbDataAdapter) this).SelectCommand, _behavior);
250 protected virtual int Fill (DataTable dataTable, IDataReader dataReader)
252 return base.FillInternal (dataTable, dataReader);
256 protected virtual int Fill (DataTable dataTable, IDbCommand command, CommandBehavior behavior)
258 CommandBehavior commandBehavior = behavior;
260 // first see that the connection is not close.
261 if (command.Connection.State == ConnectionState.Closed) {
262 command.Connection.Open ();
263 commandBehavior |= CommandBehavior.CloseConnection;
265 return Fill (dataTable, command.ExecuteReader (commandBehavior));
268 public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable)
270 return this.Fill (dataSet, startRecord, maxRecords, srcTable, ((IDbDataAdapter) this).SelectCommand, _behavior);
275 public int Fill (int startRecord, int maxRecords, params DataTable[] dataTables)
277 throw new NotImplementedException ();
281 protected virtual int Fill (DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior)
283 throw new NotImplementedException ();
286 protected virtual int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords)
288 return base.FillInternal (dataSet, srcTable, dataReader, startRecord, maxRecords);
292 protected virtual int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
294 if (command.Connection == null)
295 throw new InvalidOperationException ("Connection state is closed");
297 if (MissingSchemaAction == MissingSchemaAction.AddWithKey)
298 behavior |= CommandBehavior.KeyInfo;
299 CommandBehavior commandBehavior = behavior;
301 if (command.Connection.State == ConnectionState.Closed) {
302 command.Connection.Open ();
303 commandBehavior |= CommandBehavior.CloseConnection;
305 return Fill (dataSet, srcTable, command.ExecuteReader (commandBehavior),
306 startRecord, maxRecords);
311 /// Fills the given datatable using values from reader. if a value
312 /// for a column is null, that will be filled with default value.
314 /// <returns>No. of rows affected </returns>
315 internal static int FillFromReader (DataTable table,
320 LoadOption loadOption
323 if (reader.FieldCount == 0)
326 for (int i = 0; i < start; i++)
330 object [] values = new object [mapping.Length];
331 while (reader.Read () && (length == 0 || counter < length)) {
332 for (int i = 0 ; i < mapping.Length; i++)
333 values [i] = mapping [i] < 0 ? null : reader [mapping [i]];
334 table.BeginLoadData ();
335 table.LoadDataRow (values, loadOption);
336 table.EndLoadData ();
342 internal static int FillFromReader (DataTable table,
347 LoadOption loadOption,
348 FillErrorEventHandler errorHandler)
350 if (reader.FieldCount == 0)
353 for (int i = 0; i < start; i++)
357 object [] values = new object [mapping.Length];
358 while (reader.Read () && (length == 0 || counter < length)) {
359 for (int i = 0 ; i < mapping.Length; i++)
360 values [i] = mapping [i] < 0 ? null : reader [mapping [i]];
361 table.BeginLoadData ();
363 table.LoadDataRow (values, loadOption);
364 } catch (Exception e) {
365 FillErrorEventArgs args = new FillErrorEventArgs (table, values);
367 args.Continue = false;
368 errorHandler (table, args);
369 // if args.Continue is not set to true or if a handler is not set, rethrow the error..
373 table.EndLoadData ();
380 public override DataTable [] FillSchema (DataSet dataSet, SchemaType schemaType)
382 return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, DefaultSourceTableName, _behavior);
385 public DataTable FillSchema (DataTable dataTable, SchemaType schemaType)
387 return FillSchema (dataTable, schemaType, ((IDbDataAdapter) this).SelectCommand, _behavior);
390 public DataTable [] FillSchema (DataSet dataSet, SchemaType schemaType, string srcTable)
392 return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, srcTable, _behavior);
395 protected virtual DataTable FillSchema (DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior)
397 if (dataTable == null)
398 throw new ArgumentNullException ("DataTable");
400 behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo;
401 if (command.Connection.State == ConnectionState.Closed) {
402 command.Connection.Open ();
403 behavior |= CommandBehavior.CloseConnection;
406 IDataReader reader = command.ExecuteReader (behavior);
408 string tableName = SetupSchema (schemaType, dataTable.TableName);
409 if (tableName != null) {
410 // FillSchema should add the KeyInfo unless MissingSchemaAction
411 // is set to Ignore or Error.
412 MissingSchemaAction schemaAction = MissingSchemaAction;
413 if (!(schemaAction == MissingSchemaAction.Ignore ||
414 schemaAction == MissingSchemaAction.Error))
415 schemaAction = MissingSchemaAction.AddWithKey;
417 BuildSchema (reader, dataTable, schemaType, schemaAction,
418 MissingMappingAction, TableMappings);
426 protected virtual DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior)
429 throw new ArgumentNullException ("DataSet");
431 behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo;
432 if (command.Connection.State == ConnectionState.Closed) {
433 command.Connection.Open ();
434 behavior |= CommandBehavior.CloseConnection;
437 IDataReader reader = command.ExecuteReader (behavior);
438 ArrayList output = new ArrayList ();
439 string tableName = srcTable;
443 // FillSchema should add the KeyInfo unless MissingSchemaAction
444 // is set to Ignore or Error.
445 MissingSchemaAction schemaAction = MissingSchemaAction;
446 if (!(MissingSchemaAction == MissingSchemaAction.Ignore ||
447 MissingSchemaAction == MissingSchemaAction.Error))
448 schemaAction = MissingSchemaAction.AddWithKey;
451 tableName = SetupSchema (schemaType, tableName);
452 if (tableName != null) {
453 if (dataSet.Tables.Contains (tableName))
454 table = dataSet.Tables [tableName];
456 // Do not create schema if MissingSchemAction is set to Ignore
457 if (this.MissingSchemaAction == MissingSchemaAction.Ignore)
459 table = dataSet.Tables.Add (tableName);
462 BuildSchema (reader, table, schemaType, schemaAction,
463 MissingMappingAction, TableMappings);
465 tableName = String.Format ("{0}{1}", srcTable, ++index);
467 }while (reader.NextResult ());
471 return (DataTable []) output.ToArray (typeof (DataTable));
474 [EditorBrowsable (EditorBrowsableState.Advanced)]
475 public override IDataParameter[] GetFillParameters ()
477 IDbCommand selectCmd = ((IDbDataAdapter) this).SelectCommand;
478 IDataParameter[] parameters = new IDataParameter [selectCmd.Parameters.Count];
479 selectCmd.Parameters.CopyTo (parameters, 0);
484 [Obsolete ("use 'protected DbDataAdapter(DbDataAdapter)' ctor")]
485 object ICloneable.Clone ()
487 throw new NotImplementedException ();
490 public int Update (DataRow [] dataRows)
492 if (dataRows == null)
493 throw new ArgumentNullException("dataRows");
495 if (dataRows.Length == 0)
498 if (dataRows [0] == null)
499 throw new ArgumentException("dataRows[0].");
501 DataTable table = dataRows [0].Table;
503 throw new ArgumentException("table is null reference.");
505 // all rows must be in the same table
506 for (int i = 0; i < dataRows.Length; i++) {
507 if (dataRows [i] == null)
508 throw new ArgumentException ("dataRows[" + i + "].");
509 if (dataRows [i].Table != table)
510 throw new ArgumentException(
513 + "] is from a different DataTable than DataRow[0].");
516 // get table mapping for this rows
517 DataTableMapping tableMapping = TableMappings.GetByDataSetTable(table.TableName);
518 if (tableMapping == null) {
519 tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction(
523 MissingMappingAction);
524 if (tableMapping != null) {
525 foreach (DataColumn col in table.Columns) {
526 if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0)
528 DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction (tableMapping.ColumnMappings, col.ColumnName, MissingMappingAction);
529 if (columnMapping == null)
530 columnMapping = new DataColumnMapping (col.ColumnName, col.ColumnName);
531 tableMapping.ColumnMappings.Add (columnMapping);
534 ArrayList cmc = new ArrayList ();
535 foreach (DataColumn col in table.Columns)
536 cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName));
538 new DataTableMapping (
541 cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
545 DataRow[] copy = table.NewRowArray (dataRows.Length);
546 Array.Copy (dataRows, 0, copy, 0, dataRows.Length);
547 return Update (copy, tableMapping);
550 public override int Update (DataSet dataSet)
552 return Update (dataSet, DefaultSourceTableName);
555 public int Update (DataTable dataTable)
558 int index = TableMappings.IndexOfDataSetTable (dataTable.TableName);
560 throw new ArgumentException ();
561 return Update (dataTable, TableMappings [index]);
563 DataTableMapping tableMapping = TableMappings.GetByDataSetTable (dataTable.TableName);
564 if (tableMapping == null) {
565 tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (
569 MissingMappingAction);
570 if (tableMapping != null) {
571 foreach (DataColumn col in dataTable.Columns) {
572 if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0)
574 DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction (tableMapping.ColumnMappings, col.ColumnName, MissingMappingAction);
575 if (columnMapping == null)
576 columnMapping = new DataColumnMapping (col.ColumnName, col.ColumnName);
577 tableMapping.ColumnMappings.Add (columnMapping);
580 ArrayList cmc = new ArrayList ();
581 foreach (DataColumn col in dataTable.Columns)
582 cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName));
584 new DataTableMapping (
587 cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
590 return Update (dataTable, tableMapping);
593 private int Update (DataTable dataTable, DataTableMapping tableMapping)
595 DataRow [] rows = dataTable.NewRowArray(dataTable.Rows.Count);
596 dataTable.Rows.CopyTo (rows, 0);
597 return Update (rows, tableMapping);
600 protected virtual int Update (DataRow [] dataRows, DataTableMapping tableMapping)
603 foreach (DataRow row in dataRows) {
604 StatementType statementType = StatementType.Update;
605 IDbCommand command = null;
606 string commandName = String.Empty;
608 switch (row.RowState) {
609 case DataRowState.Added:
610 statementType = StatementType.Insert;
611 command = ((IDbDataAdapter) this).InsertCommand;
612 commandName = "Insert";
614 case DataRowState.Deleted:
615 statementType = StatementType.Delete;
616 command = ((IDbDataAdapter) this).DeleteCommand;
617 commandName = "Delete";
619 case DataRowState.Modified:
620 statementType = StatementType.Update;
621 command = ((IDbDataAdapter) this).UpdateCommand;
622 commandName = "Update";
624 case DataRowState.Unchanged:
625 case DataRowState.Detached:
629 RowUpdatingEventArgs argsUpdating = CreateRowUpdatingEvent (row, command, statementType, tableMapping);
631 OnRowUpdating (argsUpdating);
632 switch (argsUpdating.Status) {
633 case UpdateStatus.Continue :
634 //continue in update operation
636 case UpdateStatus.ErrorsOccurred :
637 if (argsUpdating.Errors == null)
638 argsUpdating.Errors = ExceptionHelper.RowUpdatedError();
639 row.RowError += argsUpdating.Errors.Message;
640 if (!ContinueUpdateOnError)
641 throw argsUpdating.Errors;
643 case UpdateStatus.SkipAllRemainingRows :
645 case UpdateStatus.SkipCurrentRow :
649 throw ExceptionHelper.InvalidUpdateStatus (argsUpdating.Status);
651 command = argsUpdating.Command;
653 if (command != null) {
654 DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
656 IDataParameter nullCheckParam = null;
658 foreach (IDataParameter parameter in command.Parameters) {
659 if ((parameter.Direction & ParameterDirection.Input) == 0)
662 DataRowVersion rowVersion = parameter.SourceVersion;
663 // Parameter version is ignored for non-update commands
664 if (statementType == StatementType.Delete)
665 rowVersion = DataRowVersion.Original;
667 string dsColumnName = parameter.SourceColumn;
669 if (columnMappings.Contains(dsColumnName)) {
670 dsColumnName = columnMappings [dsColumnName].DataSetColumn;
671 parameter.Value = row [dsColumnName, rowVersion];
673 parameter.Value = null;
676 DbParameter nullCheckParam = parameter as DbParameter;
678 if (columnMappings.Contains(dsColumnName))
679 dsColumnName = columnMappings [dsColumnName].DataSetColumn;
680 if (dsColumnName == null || dsColumnName.Length == 0) {
681 nullCheckParam = parameter;
684 parameter.Value = row [dsColumnName, rowVersion];
688 if (nullCheckParam != null && nullCheckParam.SourceColumnNullMapping) {
690 if (nullCheckParam != null) {
692 if (parameter.Value != null && parameter.Value != DBNull.Value)
693 nullCheckParam.Value = 0;
695 nullCheckParam.Value = 1;
696 nullCheckParam = null;
700 } catch (Exception e) {
701 argsUpdating.Errors = e;
702 argsUpdating.Status = UpdateStatus.ErrorsOccurred;
705 IDataReader reader = null;
708 throw ExceptionHelper.UpdateRequiresCommand (commandName);
710 CommandBehavior commandBehavior = CommandBehavior.Default;
711 if (command.Connection.State == ConnectionState.Closed) {
712 command.Connection.Open ();
713 commandBehavior |= CommandBehavior.CloseConnection;
716 // use ExecuteReader because we want to use the commandbehavior parameter.
717 // so the connection will be closed if needed.
718 reader = command.ExecuteReader (commandBehavior);
720 // update the current row, if the update command returns any resultset
721 // ignore other than the first record.
722 DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
724 if (command.UpdatedRowSource == UpdateRowSource.Both ||
725 command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) {
727 DataTable retSchema = reader.GetSchemaTable ();
728 foreach (DataRow dr in retSchema.Rows) {
729 string columnName = dr ["ColumnName"].ToString ();
730 string dstColumnName = columnName;
731 if (columnMappings != null &&
732 columnMappings.Contains(columnName))
733 dstColumnName = columnMappings [dstColumnName].DataSetColumn;
734 DataColumn dstColumn = row.Table.Columns [dstColumnName];
735 if (dstColumn == null
736 || (dstColumn.Expression != null
737 && dstColumn.Expression.Length > 0))
739 // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/
740 // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx
741 // disable readonly for non-expression columns.
742 bool readOnlyState = dstColumn.ReadOnly;
743 dstColumn.ReadOnly = false;
745 row [dstColumnName] = reader [columnName];
747 dstColumn.ReadOnly = readOnlyState;
754 int tmp = reader.RecordsAffected; // records affected is valid only after closing reader
755 // if the execute does not effect any rows we throw an exception.
757 throw new DBConcurrencyException("Concurrency violation: the " +
758 commandName +"Command affected 0 records.", null,
759 new DataRow [] { row });
762 if (command.UpdatedRowSource == UpdateRowSource.Both ||
763 command.UpdatedRowSource == UpdateRowSource.OutputParameters) {
764 // Update output parameters to row values
765 foreach (IDataParameter parameter in command.Parameters) {
766 if (parameter.Direction != ParameterDirection.InputOutput
767 && parameter.Direction != ParameterDirection.Output
768 && parameter.Direction != ParameterDirection.ReturnValue)
771 string dsColumnName = parameter.SourceColumn;
772 if (columnMappings != null &&
773 columnMappings.Contains(parameter.SourceColumn))
774 dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
775 DataColumn dstColumn = row.Table.Columns [dsColumnName];
776 if (dstColumn == null
777 || (dstColumn.Expression != null
778 && dstColumn.Expression.Length > 0))
780 bool readOnlyState = dstColumn.ReadOnly;
781 dstColumn.ReadOnly = false;
783 row [dsColumnName] = parameter.Value;
785 dstColumn.ReadOnly = readOnlyState;
790 RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent (row, command, statementType, tableMapping);
791 OnRowUpdated (updatedArgs);
792 switch (updatedArgs.Status) {
793 case UpdateStatus.Continue:
795 case UpdateStatus.ErrorsOccurred:
796 if (updatedArgs.Errors == null)
797 updatedArgs.Errors = ExceptionHelper.RowUpdatedError();
798 row.RowError += updatedArgs.Errors.Message;
799 if (!ContinueUpdateOnError)
800 throw updatedArgs.Errors;
802 case UpdateStatus.SkipCurrentRow:
804 case UpdateStatus.SkipAllRemainingRows:
808 if (!AcceptChangesDuringUpdate)
811 row.AcceptChanges ();
812 } catch (Exception e) {
813 row.RowError = e.Message;
814 if (!ContinueUpdateOnError)
817 if (reader != null && ! reader.IsClosed)
824 public int Update (DataSet dataSet, string srcTable)
826 MissingMappingAction mappingAction = MissingMappingAction;
828 if (mappingAction == MissingMappingAction.Ignore)
829 mappingAction = MissingMappingAction.Error;
831 DataTableMapping tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, srcTable, srcTable, mappingAction);
833 DataTable dataTable = dataSet.Tables [tableMapping.DataSetTable];
834 if (dataTable == null)
835 throw new ArgumentException (String.Format ("Missing table {0}",
837 return Update (dataTable, tableMapping);
841 // All the batch methods, should be implemented, if supported,
842 // by individual providers
844 protected virtual int AddToBatch (IDbCommand command)
846 throw CreateMethodNotSupportedException ();
849 protected virtual void ClearBatch ()
851 throw CreateMethodNotSupportedException ();
854 protected virtual int ExecuteBatch ()
856 throw CreateMethodNotSupportedException ();
859 protected virtual IDataParameter GetBatchedParameter (int commandIdentifier, int parameterIndex)
861 throw CreateMethodNotSupportedException ();
864 protected virtual bool GetBatchedRecordsAffected (int commandIdentifier, out int recordsAffected, out Exception error)
871 protected virtual void InitializeBatching ()
873 throw CreateMethodNotSupportedException ();
876 protected virtual void TerminateBatching ()
878 throw CreateMethodNotSupportedException ();
881 Exception CreateMethodNotSupportedException ()
883 return new NotSupportedException ("Method is not supported.");
886 internal override void OnFillErrorInternal (FillErrorEventArgs value)
891 protected virtual void OnFillError (FillErrorEventArgs value)
893 if (FillError != null)
894 FillError (this, value);
897 #endregion // Methods