2 // System.Data.Common.DbDataAdapter.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Tim Coleman (tim@timcoleman.com)
7 // Sureshkumar T <tsureshkumar@novell.com>
10 // Copyright (C) Tim Coleman, 2002-2003
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Collections;
38 using System.ComponentModel;
40 using System.Reflection;
41 using System.Runtime.InteropServices;
43 namespace System.Data.Common
46 public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable
48 public abstract class DbDataAdapter : DataAdapter, ICloneable
53 public const string DefaultSourceTableName = "Table";
54 const string DefaultSourceColumnName = "Column";
55 CommandBehavior _behavior = CommandBehavior.Default;
58 IDbCommand _selectCommand;
59 IDbCommand _updateCommand;
60 IDbCommand _deleteCommand;
61 IDbCommand _insertCommand;
68 protected DbDataAdapter ()
72 protected DbDataAdapter (DbDataAdapter adapter) : base (adapter)
81 protected internal CommandBehavior FillCommandBehavior {
82 get { return _behavior; }
83 set { _behavior = value; }
86 IDbCommand IDbDataAdapter.SelectCommand {
87 get { return _selectCommand; }
88 set { _selectCommand = value; }
91 IDbCommand IDbDataAdapter.UpdateCommand{
92 get { return _updateCommand; }
93 set { _updateCommand = value; }
96 IDbCommand IDbDataAdapter.DeleteCommand{
97 get { return _deleteCommand; }
98 set { _deleteCommand = value; }
101 IDbCommand IDbDataAdapter.InsertCommand{
102 get { return _insertCommand; }
103 set { _insertCommand = value; }
107 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
108 public DbCommand SelectCommand {
109 get { return (DbCommand) ((IDbDataAdapter) this).SelectCommand; }
110 set { ((IDbDataAdapter) this).SelectCommand = value; }
114 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
115 public DbCommand DeleteCommand {
116 get { return (DbCommand) ((IDbDataAdapter) this).DeleteCommand; }
117 set { ((IDbDataAdapter) this).DeleteCommand = value; }
121 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
122 public DbCommand InsertCommand {
123 get { return (DbCommand) ((IDbDataAdapter) this).InsertCommand; }
124 set { ((IDbDataAdapter) this).InsertCommand = value; }
128 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
129 public DbCommand UpdateCommand {
130 get { return (DbCommand) ((IDbDataAdapter) this).UpdateCommand; }
131 set { ((IDbDataAdapter) this).UpdateCommand = value; }
135 public virtual int UpdateBatchSize {
139 throw new NotSupportedException ();
143 IDbCommand SelectCommand {
144 get { return ((IDbDataAdapter) this).SelectCommand; }
147 IDbCommand UpdateCommand {
148 get { return ((IDbDataAdapter) this).UpdateCommand; }
151 IDbCommand DeleteCommand {
152 get { return ((IDbDataAdapter) this).DeleteCommand; }
155 IDbCommand InsertCommand {
156 get { return ((IDbDataAdapter) this).InsertCommand; }
160 #endregion // Properties
164 #if ONLY_1_0 || ONLY_1_1
165 [DataCategory ("Fill")]
166 [DataSysDescription ("Event triggered when a recoverable error occurs during Fill.")]
167 public event FillErrorEventHandler FillError;
175 protected virtual RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
176 StatementType statementType,
177 DataTableMapping tableMapping)
179 return new RowUpdatedEventArgs (dataRow, command, statementType, tableMapping);
182 protected virtual RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
183 StatementType statementType,
184 DataTableMapping tableMapping)
186 return new RowUpdatingEventArgs (dataRow, command, statementType, tableMapping);
189 protected virtual void OnRowUpdated (RowUpdatedEventArgs value)
191 if (Events ["RowUpdated"] != null) {
192 Delegate [] rowUpdatedList = Events ["RowUpdated"].GetInvocationList ();
193 foreach (Delegate rowUpdated in rowUpdatedList) {
194 MethodInfo rowUpdatedMethod = rowUpdated.Method;
195 rowUpdatedMethod.Invoke (value, null);
200 protected virtual void OnRowUpdating (RowUpdatingEventArgs value)
202 if (Events ["RowUpdating"] != null) {
203 Delegate [] rowUpdatingList = Events ["RowUpdating"].GetInvocationList ();
204 foreach (Delegate rowUpdating in rowUpdatingList) {
205 MethodInfo rowUpdatingMethod = rowUpdating.Method;
206 rowUpdatingMethod.Invoke (value, null);
211 protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
212 StatementType statementType,
213 DataTableMapping tableMapping);
215 protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
216 StatementType statementType,
217 DataTableMapping tableMapping);
219 protected abstract void OnRowUpdated (RowUpdatedEventArgs value);
220 protected abstract void OnRowUpdating (RowUpdatingEventArgs value);
223 protected override void Dispose (bool disposing)
226 IDbDataAdapter da = (IDbDataAdapter) this;
227 if (da.SelectCommand != null) {
228 da.SelectCommand.Dispose();
229 da.SelectCommand = null;
231 if (da.InsertCommand != null) {
232 da.InsertCommand.Dispose();
233 da.InsertCommand = null;
235 if (da.UpdateCommand != null) {
236 da.UpdateCommand.Dispose();
237 da.UpdateCommand = null;
239 if (da.DeleteCommand != null) {
240 da.DeleteCommand.Dispose();
241 da.DeleteCommand = null;
246 public override int Fill (DataSet dataSet)
248 return Fill (dataSet, 0, 0, DefaultSourceTableName, ((IDbDataAdapter) this).SelectCommand, _behavior);
251 public int Fill (DataTable dataTable)
253 if (dataTable == null)
254 throw new ArgumentNullException ("DataTable");
256 return Fill (dataTable, ((IDbDataAdapter) this).SelectCommand, _behavior);
259 public int Fill (DataSet dataSet, string srcTable)
261 return Fill (dataSet, 0, 0, srcTable, ((IDbDataAdapter) this).SelectCommand, _behavior);
265 protected virtual int Fill (DataTable dataTable, IDataReader dataReader)
267 return base.FillInternal (dataTable, dataReader);
271 protected virtual int Fill (DataTable dataTable, IDbCommand command, CommandBehavior behavior)
273 CommandBehavior commandBehavior = behavior;
275 // first see that the connection is not close.
276 if (command.Connection.State == ConnectionState.Closed) {
277 command.Connection.Open ();
278 commandBehavior |= CommandBehavior.CloseConnection;
280 return Fill (dataTable, command.ExecuteReader (commandBehavior));
283 public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable)
285 return this.Fill (dataSet, startRecord, maxRecords, srcTable, ((IDbDataAdapter) this).SelectCommand, _behavior);
290 public int Fill (int startRecord, int maxRecords, params DataTable[] dataTables)
292 throw new NotImplementedException ();
296 protected virtual int Fill (DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior)
298 throw new NotImplementedException ();
301 protected virtual int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords)
303 return base.FillInternal (dataSet, srcTable, dataReader, startRecord, maxRecords);
307 protected virtual int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
309 if (command.Connection == null)
310 throw new InvalidOperationException ("Connection state is closed");
312 if (MissingSchemaAction == MissingSchemaAction.AddWithKey)
313 behavior |= CommandBehavior.KeyInfo;
314 CommandBehavior commandBehavior = behavior;
316 if (command.Connection.State == ConnectionState.Closed) {
317 command.Connection.Open ();
318 commandBehavior |= CommandBehavior.CloseConnection;
320 return Fill (dataSet, srcTable, command.ExecuteReader (commandBehavior),
321 startRecord, maxRecords);
326 /// Fills the given datatable using values from reader. if a value
327 /// for a column is null, that will be filled with default value.
329 /// <returns>No. of rows affected </returns>
330 internal static int FillFromReader (DataTable table,
335 LoadOption loadOption
338 if (reader.FieldCount == 0)
341 for (int i = 0; i < start; i++)
345 object [] values = new object [mapping.Length];
346 while (reader.Read () && (length == 0 || counter < length)) {
347 for (int i = 0 ; i < mapping.Length; i++)
348 values [i] = mapping [i] < 0 ? null : reader [mapping [i]];
349 table.BeginLoadData ();
350 table.LoadDataRow (values, loadOption);
351 table.EndLoadData ();
357 internal static int FillFromReader (DataTable table,
362 LoadOption loadOption,
363 FillErrorEventHandler errorHandler)
365 if (reader.FieldCount == 0)
368 for (int i = 0; i < start; i++)
372 object [] values = new object [mapping.Length];
373 while (reader.Read () && (length == 0 || counter < length)) {
374 for (int i = 0 ; i < mapping.Length; i++)
375 values [i] = mapping [i] < 0 ? null : reader [mapping [i]];
376 table.BeginLoadData ();
378 table.LoadDataRow (values, loadOption);
379 } catch (Exception e) {
380 FillErrorEventArgs args = new FillErrorEventArgs (table, values);
382 args.Continue = false;
383 errorHandler (table, args);
384 // if args.Continue is not set to true or if a handler is not set, rethrow the error..
388 table.EndLoadData ();
395 public override DataTable [] FillSchema (DataSet dataSet, SchemaType schemaType)
397 return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, DefaultSourceTableName, _behavior);
400 public DataTable FillSchema (DataTable dataTable, SchemaType schemaType)
402 return FillSchema (dataTable, schemaType, ((IDbDataAdapter) this).SelectCommand, _behavior);
405 public DataTable [] FillSchema (DataSet dataSet, SchemaType schemaType, string srcTable)
407 return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, srcTable, _behavior);
410 protected virtual DataTable FillSchema (DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior)
412 if (dataTable == null)
413 throw new ArgumentNullException ("DataTable");
415 behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo;
416 if (command.Connection.State == ConnectionState.Closed) {
417 command.Connection.Open ();
418 behavior |= CommandBehavior.CloseConnection;
421 IDataReader reader = command.ExecuteReader (behavior);
423 string tableName = SetupSchema (schemaType, dataTable.TableName);
424 if (tableName != null) {
425 // FillSchema should add the KeyInfo unless MissingSchemaAction
426 // is set to Ignore or Error.
427 MissingSchemaAction schemaAction = MissingSchemaAction;
428 if (!(schemaAction == MissingSchemaAction.Ignore ||
429 schemaAction == MissingSchemaAction.Error))
430 schemaAction = MissingSchemaAction.AddWithKey;
432 BuildSchema (reader, dataTable, schemaType, schemaAction,
433 MissingMappingAction, TableMappings);
441 protected virtual DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior)
444 throw new ArgumentNullException ("DataSet");
446 behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo;
447 if (command.Connection.State == ConnectionState.Closed) {
448 command.Connection.Open ();
449 behavior |= CommandBehavior.CloseConnection;
452 IDataReader reader = command.ExecuteReader (behavior);
453 ArrayList output = new ArrayList ();
454 string tableName = srcTable;
458 // FillSchema should add the KeyInfo unless MissingSchemaAction
459 // is set to Ignore or Error.
460 MissingSchemaAction schemaAction = MissingSchemaAction;
461 if (!(MissingSchemaAction == MissingSchemaAction.Ignore ||
462 MissingSchemaAction == MissingSchemaAction.Error))
463 schemaAction = MissingSchemaAction.AddWithKey;
466 tableName = SetupSchema (schemaType, tableName);
467 if (tableName != null) {
468 if (dataSet.Tables.Contains (tableName))
469 table = dataSet.Tables [tableName];
471 // Do not create schema if MissingSchemAction is set to Ignore
472 if (this.MissingSchemaAction == MissingSchemaAction.Ignore)
474 table = dataSet.Tables.Add (tableName);
477 BuildSchema (reader, table, schemaType, schemaAction,
478 MissingMappingAction, TableMappings);
480 tableName = String.Format ("{0}{1}", srcTable, ++index);
482 }while (reader.NextResult ());
486 return (DataTable []) output.ToArray (typeof (DataTable));
489 [EditorBrowsable (EditorBrowsableState.Advanced)]
490 public override IDataParameter[] GetFillParameters ()
492 IDataParameter[] parameters = new IDataParameter [SelectCommand.Parameters.Count];
493 SelectCommand.Parameters.CopyTo (parameters, 0);
498 [Obsolete ("use 'protected DbDataAdapter(DbDataAdapter)' ctor")]
499 object ICloneable.Clone ()
501 throw new NotImplementedException ();
504 public int Update (DataRow [] dataRows)
506 if (dataRows == null)
507 throw new ArgumentNullException("dataRows");
509 if (dataRows.Length == 0)
512 if (dataRows [0] == null)
513 throw new ArgumentException("dataRows[0].");
515 DataTable table = dataRows [0].Table;
517 throw new ArgumentException("table is null reference.");
519 // all rows must be in the same table
520 for (int i = 0; i < dataRows.Length; i++) {
521 if (dataRows [i] == null)
522 throw new ArgumentException ("dataRows[" + i + "].");
523 if (dataRows [i].Table != table)
524 throw new ArgumentException(
527 + "] is from a different DataTable than DataRow[0].");
530 // get table mapping for this rows
531 DataTableMapping tableMapping = TableMappings.GetByDataSetTable(table.TableName);
532 if (tableMapping == null) {
533 tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction(
537 MissingMappingAction);
538 if (tableMapping != null) {
539 foreach (DataColumn col in table.Columns) {
540 if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0)
542 DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction (tableMapping.ColumnMappings, col.ColumnName, MissingMappingAction);
543 if (columnMapping == null)
544 columnMapping = new DataColumnMapping (col.ColumnName, col.ColumnName);
545 tableMapping.ColumnMappings.Add (columnMapping);
548 ArrayList cmc = new ArrayList ();
549 foreach (DataColumn col in table.Columns)
550 cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName));
552 new DataTableMapping (
555 cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
559 DataRow[] copy = table.NewRowArray (dataRows.Length);
560 Array.Copy (dataRows, 0, copy, 0, dataRows.Length);
561 return Update (copy, tableMapping);
564 public override int Update (DataSet dataSet)
566 return Update (dataSet, DefaultSourceTableName);
569 public int Update (DataTable dataTable)
572 int index = TableMappings.IndexOfDataSetTable (dataTable.TableName);
574 throw new ArgumentException ();
575 return Update (dataTable, TableMappings [index]);
577 DataTableMapping tableMapping = TableMappings.GetByDataSetTable (dataTable.TableName);
578 if (tableMapping == null) {
579 tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (
583 MissingMappingAction);
584 if (tableMapping != null) {
585 foreach (DataColumn col in dataTable.Columns) {
586 if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0)
588 DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction (tableMapping.ColumnMappings, col.ColumnName, MissingMappingAction);
589 if (columnMapping == null)
590 columnMapping = new DataColumnMapping (col.ColumnName, col.ColumnName);
591 tableMapping.ColumnMappings.Add (columnMapping);
594 ArrayList cmc = new ArrayList ();
595 foreach (DataColumn col in dataTable.Columns)
596 cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName));
598 new DataTableMapping (
601 cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
604 return Update (dataTable, tableMapping);
607 private int Update (DataTable dataTable, DataTableMapping tableMapping)
609 DataRow [] rows = dataTable.NewRowArray(dataTable.Rows.Count);
610 dataTable.Rows.CopyTo (rows, 0);
611 return Update (rows, tableMapping);
614 protected virtual int Update (DataRow [] dataRows, DataTableMapping tableMapping)
617 foreach (DataRow row in dataRows) {
618 StatementType statementType = StatementType.Update;
619 IDbCommand command = null;
620 string commandName = String.Empty;
622 switch (row.RowState) {
623 case DataRowState.Added:
624 statementType = StatementType.Insert;
625 command = ((IDbDataAdapter) this).InsertCommand;
626 commandName = "Insert";
628 case DataRowState.Deleted:
629 statementType = StatementType.Delete;
630 command = ((IDbDataAdapter) this).DeleteCommand;
631 commandName = "Delete";
633 case DataRowState.Modified:
634 statementType = StatementType.Update;
635 command = ((IDbDataAdapter) this).UpdateCommand;
636 commandName = "Update";
638 case DataRowState.Unchanged:
639 case DataRowState.Detached:
643 RowUpdatingEventArgs argsUpdating = CreateRowUpdatingEvent (row, command, statementType, tableMapping);
645 OnRowUpdating (argsUpdating);
646 switch (argsUpdating.Status) {
647 case UpdateStatus.Continue :
648 //continue in update operation
650 case UpdateStatus.ErrorsOccurred :
651 if (argsUpdating.Errors == null)
652 argsUpdating.Errors = ExceptionHelper.RowUpdatedError();
653 row.RowError += argsUpdating.Errors.Message;
654 if (!ContinueUpdateOnError)
655 throw argsUpdating.Errors;
657 case UpdateStatus.SkipAllRemainingRows :
659 case UpdateStatus.SkipCurrentRow :
663 throw ExceptionHelper.InvalidUpdateStatus (argsUpdating.Status);
665 command = argsUpdating.Command;
667 if (command != null) {
668 DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
669 IDataParameter nullCheckParam = null;
670 foreach (IDataParameter parameter in command.Parameters) {
671 if ((parameter.Direction & ParameterDirection.Input) != 0) {
672 string dsColumnName = parameter.SourceColumn;
673 if (columnMappings.Contains(parameter.SourceColumn))
674 dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
675 if (dsColumnName == null || dsColumnName.Length <= 0) {
676 nullCheckParam = parameter;
680 DataRowVersion rowVersion = parameter.SourceVersion;
681 // Parameter version is ignored for non-update commands
682 if (statementType == StatementType.Delete)
683 rowVersion = DataRowVersion.Original;
685 parameter.Value = row [dsColumnName, rowVersion];
686 if (nullCheckParam != null && (parameter.Value != null
687 && parameter.Value != DBNull.Value)) {
688 nullCheckParam.Value = 0;
689 nullCheckParam = null;
694 } catch (Exception e) {
695 argsUpdating.Errors = e;
696 argsUpdating.Status = UpdateStatus.ErrorsOccurred;
699 IDataReader reader = null;
702 throw ExceptionHelper.UpdateRequiresCommand (commandName);
704 CommandBehavior commandBehavior = CommandBehavior.Default;
705 if (command.Connection.State == ConnectionState.Closed) {
706 command.Connection.Open ();
707 commandBehavior |= CommandBehavior.CloseConnection;
710 // use ExecuteReader because we want to use the commandbehavior parameter.
711 // so the connection will be closed if needed.
712 reader = command.ExecuteReader (commandBehavior);
714 // update the current row, if the update command returns any resultset
715 // ignore other than the first record.
716 DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
718 if (command.UpdatedRowSource == UpdateRowSource.Both ||
719 command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) {
721 DataTable retSchema = reader.GetSchemaTable ();
722 foreach (DataRow dr in retSchema.Rows) {
723 string columnName = dr ["ColumnName"].ToString ();
724 string dstColumnName = columnName;
725 if (columnMappings != null &&
726 columnMappings.Contains(columnName))
727 dstColumnName = columnMappings [dstColumnName].DataSetColumn;
728 DataColumn dstColumn = row.Table.Columns [dstColumnName];
729 if (dstColumn == null
730 || (dstColumn.Expression != null
731 && dstColumn.Expression.Length > 0))
733 // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/
734 // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx
735 // disable readonly for non-expression columns.
736 bool readOnlyState = dstColumn.ReadOnly;
737 dstColumn.ReadOnly = false;
739 row [dstColumnName] = reader [columnName];
741 dstColumn.ReadOnly = readOnlyState;
748 int tmp = reader.RecordsAffected; // records affected is valid only after closing reader
749 // if the execute does not effect any rows we throw an exception.
751 throw new DBConcurrencyException("Concurrency violation: the " +
752 commandName +"Command affected 0 records.");
755 if (command.UpdatedRowSource == UpdateRowSource.Both ||
756 command.UpdatedRowSource == UpdateRowSource.OutputParameters) {
757 // Update output parameters to row values
758 foreach (IDataParameter parameter in command.Parameters) {
759 if (parameter.Direction != ParameterDirection.InputOutput
760 && parameter.Direction != ParameterDirection.Output
761 && parameter.Direction != ParameterDirection.ReturnValue)
764 string dsColumnName = parameter.SourceColumn;
765 if (columnMappings != null &&
766 columnMappings.Contains(parameter.SourceColumn))
767 dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
768 DataColumn dstColumn = row.Table.Columns [dsColumnName];
769 if (dstColumn == null
770 || (dstColumn.Expression != null
771 && dstColumn.Expression.Length > 0))
773 bool readOnlyState = dstColumn.ReadOnly;
774 dstColumn.ReadOnly = false;
776 row [dsColumnName] = parameter.Value;
778 dstColumn.ReadOnly = readOnlyState;
783 RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent (row, command, statementType, tableMapping);
784 OnRowUpdated (updatedArgs);
785 switch (updatedArgs.Status) {
786 case UpdateStatus.Continue:
788 case UpdateStatus.ErrorsOccurred:
789 if (updatedArgs.Errors == null)
790 updatedArgs.Errors = ExceptionHelper.RowUpdatedError();
791 row.RowError += updatedArgs.Errors.Message;
792 if (!ContinueUpdateOnError)
793 throw updatedArgs.Errors;
795 case UpdateStatus.SkipCurrentRow:
797 case UpdateStatus.SkipAllRemainingRows:
801 if (!AcceptChangesDuringUpdate)
804 row.AcceptChanges ();
805 } catch (Exception e) {
806 row.RowError = e.Message;
807 if (!ContinueUpdateOnError)
810 if (reader != null && ! reader.IsClosed)
817 public int Update (DataSet dataSet, string srcTable)
819 MissingMappingAction mappingAction = MissingMappingAction;
821 if (mappingAction == MissingMappingAction.Ignore)
822 mappingAction = MissingMappingAction.Error;
824 DataTableMapping tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, srcTable, srcTable, mappingAction);
826 DataTable dataTable = dataSet.Tables [tableMapping.DataSetTable];
827 if (dataTable == null)
828 throw new ArgumentException (String.Format ("Missing table {0}",
830 return Update (dataTable, tableMapping);
834 // All the batch methods, should be implemented, if supported,
835 // by individual providers
837 protected virtual int AddToBatch (IDbCommand command)
839 throw CreateMethodNotSupportedException ();
842 protected virtual void ClearBatch ()
844 throw CreateMethodNotSupportedException ();
847 protected virtual int ExecuteBatch ()
849 throw CreateMethodNotSupportedException ();
852 protected virtual IDataParameter GetBatchedParameter (int commandIdentifier, int parameterIndex)
854 throw CreateMethodNotSupportedException ();
857 protected virtual bool GetBatchedRecordsAffected (int commandIdentifier, out int recordsAffected, out Exception error)
864 protected virtual void InitializeBatching ()
866 throw CreateMethodNotSupportedException ();
869 protected virtual void TerminateBatching ()
871 throw CreateMethodNotSupportedException ();
874 Exception CreateMethodNotSupportedException ()
876 return new NotSupportedException ("Method is not supported.");
879 internal override void OnFillErrorInternal (FillErrorEventArgs value)
884 protected virtual void OnFillError (FillErrorEventArgs value)
886 if (FillError != null)
887 FillError (this, value);
890 #endregion // Methods