New test.
[mono.git] / mcs / class / System.Data / System.Data.Common / DbDataAdapter.cs
index a895a21cc8183bdc54710273329d2ae0a296aebb..9e98ef92d97a5e6efc2cfd8738d734ced793260f 100644 (file)
@@ -40,13 +40,24 @@ using System.Data;
 using System.Runtime.InteropServices;
 
 namespace System.Data.Common {
+#if NET_2_0
+       public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable
+#else
        public abstract class DbDataAdapter : DataAdapter, ICloneable
+#endif
        {
                #region Fields
 
                public const string DefaultSourceTableName = "Table";
                const string DefaultSourceColumnName = "Column";
 
+#if NET_2_0
+               IDbCommand _selectCommand;
+               internal IDbCommand _updateCommand;
+               internal IDbCommand _deleteCommand;
+               internal IDbCommand _insertCommand;
+#endif
+
                #endregion // Fields
                
                #region Constructors
@@ -55,7 +66,6 @@ namespace System.Data.Common {
                {
                }
 
-               [MonoTODO]
                protected DbDataAdapter(DbDataAdapter adapter) : base(adapter)
                {
                }
@@ -65,68 +75,84 @@ namespace System.Data.Common {
                #region Properties
 
 #if NET_2_0
-               [MonoTODO]
-               protected virtual IDbConnection BaseConnection {
+               protected internal CommandBehavior FillCommandBehavior {
                        get { throw new NotImplementedException (); }
                        set { throw new NotImplementedException (); }
                }
 
-               public IDbConnection Connection { 
-                       get { return BaseConnection; }
-                       set { BaseConnection = value; }
+               IDbCommand IDbDataAdapter.SelectCommand {
+                       get { return _selectCommand; }
+                       set { _selectCommand = value; }
                }
-#endif
 
-               IDbCommand DeleteCommand {
-                       get { return ((IDbDataAdapter) this).DeleteCommand; }
+               IDbCommand IDbDataAdapter.UpdateCommand{
+                       get { return _updateCommand; }
+                       set { _updateCommand = value; }
                }
 
-#if NET_2_0
-               protected internal CommandBehavior FillCommandBehavior {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+               IDbCommand IDbDataAdapter.DeleteCommand{
+                       get { return _deleteCommand; }
+                       set { _deleteCommand = value; }
                }
-#endif
 
-               IDbCommand InsertCommand {
-                       get { return ((IDbDataAdapter) this).InsertCommand; }
+               IDbCommand IDbDataAdapter.InsertCommand{
+                       get { return _insertCommand; }
+                       set { _insertCommand = value; }
                }
-
-#if NET_2_0
-               [MonoTODO]
-               protected virtual IDbCommand this [[Optional] StatementType statementType] {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+               
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               public DbCommand SelectCommand {
+                       get { return (DbCommand) ((IDbDataAdapter) this).SelectCommand; }
+                       set { ((IDbDataAdapter) this).SelectCommand = value; }
                }
 
-               protected virtual DbProviderFactory ProviderFactory {
-                       get { throw new NotImplementedException (); }
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               public DbCommand DeleteCommand {
+                       get { return (DbCommand) ((IDbDataAdapter) this).DeleteCommand; }
+                       set { ((IDbDataAdapter) this).DeleteCommand = value; }
                }
-#endif
 
-               IDbCommand SelectCommand {
-                       get { return ((IDbDataAdapter) this).SelectCommand; }
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               public DbCommand InsertCommand {
+                       get { return (DbCommand) ((IDbDataAdapter) this).InsertCommand; }
+                       set { ((IDbDataAdapter) this).InsertCommand = value; }
                }
 
-#if NET_2_0
-               [MonoTODO]
-               public IDbTransaction Transaction {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               public DbCommand UpdateCommand {
+                       get { return (DbCommand) ((IDbDataAdapter) this).UpdateCommand; }
+                       set { ((IDbDataAdapter) this).UpdateCommand = value; }
                }
 
                [MonoTODO]
-               public int UpdateBatchSize {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+               [DefaultValue (1)]
+               public virtual int UpdateBatchSize {
+                       get { return 1; }
+                       set { throw new NotSupportedException (); }
+               }
+#else
+               IDbCommand SelectCommand {
+                       get { return ((IDbDataAdapter) this).SelectCommand; }
                }
-#endif
 
                IDbCommand UpdateCommand {
                        get { return ((IDbDataAdapter) this).UpdateCommand; }
                }
 
-               #endregion // Properties
+               IDbCommand DeleteCommand {
+                       get { return ((IDbDataAdapter) this).DeleteCommand; }
+               }
+
+               IDbCommand InsertCommand {
+                       get { return ((IDbDataAdapter) this).InsertCommand; }
+               } 
+#endif
+
+               #endregion // Properties
                
                #region Events
 
@@ -142,15 +168,44 @@ namespace System.Data.Common {
                #region Methods
 
 #if NET_2_0
+               protected virtual RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
+                                                                            StatementType statementType,
+                                                                            DataTableMapping tableMapping)
+               {
+                       return new RowUpdatedEventArgs (dataRow, command, statementType, tableMapping);
+               }
+
+               protected virtual RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
+                                                                              StatementType statementType,
+                                                                              DataTableMapping tableMapping)
+               {
+                       return new RowUpdatingEventArgs (dataRow, command, statementType, tableMapping);
+               }
+
+               [MonoTODO]
+               protected virtual void OnRowUpdated (RowUpdatedEventArgs value)
+               {
+                       throw new NotImplementedException ();
+               }
+
                [MonoTODO]
-               public virtual void BeginInit ()
+               protected virtual void OnRowUpdating (RowUpdatingEventArgs value)
                {
                        throw new NotImplementedException ();
                }
+#else
+               protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
+                                                                            StatementType statementType,
+                                                                            DataTableMapping tableMapping);
+
+               protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
+                                                                              StatementType statementType,
+                                                                              DataTableMapping tableMapping);
+
+               protected abstract void OnRowUpdated (RowUpdatedEventArgs value);
+               protected abstract void OnRowUpdating (RowUpdatingEventArgs value);
 #endif
 
-               protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping);
-               protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping);
 
                private FillErrorEventArgs CreateFillErrorEvent (DataTable dataTable, object[] values, Exception e)
                {
@@ -169,7 +224,7 @@ namespace System.Data.Common {
                                        da.SelectCommand = null;
                                }
                                if (da.InsertCommand != null) {
-                                        da.InsertCommand.Dispose();
+                                       da.InsertCommand.Dispose();
                                        da.InsertCommand = null;
                                }
                                if (da.UpdateCommand != null) {
@@ -183,37 +238,31 @@ namespace System.Data.Common {
                        }
                }
 
-#if NET_2_0
-               [MonoTODO]
-               public virtual void EndInit ()
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
                public override int Fill (DataSet dataSet)
                {
-                       return Fill (dataSet, 0, 0, DefaultSourceTableName, SelectCommand, CommandBehavior.Default);
+                       return Fill (dataSet, 0, 0, DefaultSourceTableName, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
                }
 
                public int Fill (DataTable dataTable) 
                {
                        if (dataTable == null)
-                               throw new NullReferenceException ();
+                               throw new ArgumentNullException ("DataTable");
 
-                       return Fill (dataTable, SelectCommand, CommandBehavior.Default);
+                       return Fill (dataTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
                }
 
                public int Fill (DataSet dataSet, string srcTable) 
                {
-                       return Fill (dataSet, 0, 0, srcTable, SelectCommand, CommandBehavior.Default);
+                       return Fill (dataSet, 0, 0, srcTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
                }
 
 #if NET_2_0
-               protected override int Fill (DataTable dataTable, IDataReader dataReader) 
+               [MonoTODO ("This needs to be moved to DataAdapter.For now, just override")]
+               protected override
 #else
-               protected virtual int Fill (DataTable dataTable, IDataReader dataReader) 
+               protected virtual 
 #endif
+               int Fill (DataTable dataTable, IDataReader dataReader) 
                {
                        if (dataReader.FieldCount == 0) {
                                dataReader.Close ();
@@ -238,6 +287,7 @@ namespace System.Data.Common {
                protected virtual int Fill (DataTable dataTable, IDbCommand command, CommandBehavior behavior) 
                {
                        CommandBehavior commandBehavior = behavior;
+
                        // first see that the connection is not close.
                        if (command.Connection.State == ConnectionState.Closed) 
                        {
@@ -247,39 +297,43 @@ namespace System.Data.Common {
                        return Fill (dataTable, command.ExecuteReader (commandBehavior));
                }
 
+               public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable) 
+               {
+                       return this.Fill (dataSet, startRecord, maxRecords, srcTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
+               }
+
 #if NET_2_0
                [MonoTODO]
                public int Fill (int startRecord, int maxRecords, DataTable[] dataTables)
                {
                        throw new NotImplementedException ();
                }
-#endif
-
-               public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable) 
-               {
-                       return this.Fill (dataSet, startRecord, maxRecords, srcTable, SelectCommand, CommandBehavior.Default);
-               }
 
-#if NET_2_0
                [MonoTODO]
                protected virtual int Fill (DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior)
                {
                        throw new NotImplementedException ();
                }
 #endif
-
+               
+               
 #if NET_2_0
-               protected override int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) 
+               [MonoTODO ("This needs to be moved to DataAdapter.For now, just override")]
+               protected override
 #else
-               protected virtual int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) 
+               protected virtual
 #endif
+               int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) 
                {
+                       if (dataSet == null)
+                               throw new ArgumentNullException ("DataSet");
+
                        if (startRecord < 0)
                                throw new ArgumentException ("The startRecord parameter was less than 0.");
                        if (maxRecords < 0)
                                throw new ArgumentException ("The maxRecords parameter was less than 0.");
 
-                       DataTable dataTable;
+                       DataTable dataTable = null;
                        int resultIndex = 0;
                        int count = 0;
                        
@@ -287,18 +341,20 @@ namespace System.Data.Common {
                                string tableName = srcTable;
                                do {
                                        // Non-resultset queries like insert, delete or update aren't processed.
-                    if (dataReader.FieldCount != -1)
+                                       if (dataReader.FieldCount != -1)
                                        {
                                                tableName = SetupSchema (SchemaType.Mapped, tableName);
                                                if (tableName != null) {
-                                               
+                                                       
                                                        // check if the table exists in the dataset
                                                        if (dataSet.Tables.Contains (tableName)) 
                                                                // get the table from the dataset
                                                                dataTable = dataSet.Tables [tableName];
                                                        else {
-                                                               dataTable = new DataTable(tableName);
-                                                               dataSet.Tables.Add (dataTable);
+                                                               // Do not create schema if MissingSchemAction is set to Ignore
+                                                               if (this.MissingSchemaAction == MissingSchemaAction.Ignore)
+                                                                       continue;
+                                                               dataTable = dataSet.Tables.Add (tableName);
                                                        }
        
                                                        if (!FillTable (dataTable, dataReader, startRecord, maxRecords, ref count)) {
@@ -323,8 +379,9 @@ namespace System.Data.Common {
                protected virtual int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior) 
                {
                        if (MissingSchemaAction == MissingSchemaAction.AddWithKey)
-                           behavior |= CommandBehavior.KeyInfo;
+                               behavior |= CommandBehavior.KeyInfo;
                        CommandBehavior commandBehavior = behavior;
+
                        if (command.Connection.State == ConnectionState.Closed) {
                                command.Connection.Open ();
                                commandBehavior |= CommandBehavior.CloseConnection;
@@ -340,7 +397,7 @@ namespace System.Data.Common {
                        int counterStart = counter;
 
                        int[] mapping = BuildSchema (dataReader, dataTable, SchemaType.Mapped);
-
+                       
                        int[] sortedMapping = new int[mapping.Length];
                        int length = sortedMapping.Length;
                        for(int i=0; i < sortedMapping.Length; i++) {
@@ -350,17 +407,16 @@ namespace System.Data.Common {
                                        sortedMapping[--length] = i;
                        }
 
-                               for (int i = 0; i < startRecord; i++) {
-                                       dataReader.Read ();
-                               }
+                       for (int i = 0; i < startRecord; i++) {
+                               dataReader.Read ();
+                       }
 
+                       dataTable.BeginLoadData ();
                        while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) {
                                try {
-                                       dataTable.BeginLoadData ();
                                        dataTable.LoadDataRow (dataReader, sortedMapping, length, AcceptChangesDuringFill);
-                                       dataTable.EndLoadData ();
                                        counter++;
-                               } 
+                               }
                                catch (Exception e) {
                                        object[] readerArray = new object[dataReader.FieldCount];
                                        object[] tableArray = new object[mapping.Length];
@@ -374,20 +430,22 @@ namespace System.Data.Common {
                                        }
                                        FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e);
                                        OnFillError (args);
-                                       if(!args.Continue) {
-                                               return false;
-                                       }
+
+                                       // if args.Continue is not set to true or if a handler is not set, rethrow the error..
+                                       if(!args.Continue)
+                                               throw e;
                                }
                        }
+                       dataTable.EndLoadData ();
                        return true;
                }
 
 #if NET_2_0
-                /// <summary>
-                ///     Fills the given datatable using values from reader. if a value 
-                ///     for a column is  null, that will be filled with default value. 
-                /// </summary>
-                /// <returns>No. of rows affected </returns>
+               /// <summary>
+               ///     Fills the given datatable using values from reader. if a value 
+               ///     for a column is  null, that will be filled with default value. 
+               /// </summary>
+               /// <returns>No. of rows affected </returns>
                internal static int FillFromReader (DataTable table,
                                                     IDataReader reader,
                                                     int start, 
@@ -418,26 +476,68 @@ namespace System.Data.Common {
                         return counter;
                 }
 
+               internal static int FillFromReader (DataTable table,
+                                                    IDataReader reader,
+                                                    int start, 
+                                                    int length,
+                                                    int [] mapping,
+                                                    LoadOption loadOption,
+                                                    FillErrorEventHandler errorHandler)
+                {
+                        if (reader.FieldCount == 0)
+                               return 0 ;
+
+                        for (int i = 0; i < start; i++)
+                                reader.Read ();
+
+                        int counter = 0;
+                        object [] values = new object [mapping.Length];
+                        while (reader.Read () &&
+                               (length == 0 || counter < length)) {
+                                
+                                for (int i = 0 ; i < mapping.Length; i++)
+                                        values [i] = mapping [i] < 0 ? null : reader [mapping [i]];
+                                        
+                                table.BeginLoadData ();
+                               try {
+                                       table.LoadDataRow (values, loadOption);
+                               } catch (Exception e) {
+                                       FillErrorEventArgs args = new FillErrorEventArgs (table, values);
+                                       args.Errors = e;
+                                       args.Continue = false;
+                                       errorHandler (table, args);
+                                       // if args.Continue is not set to true or if a handler is not set, rethrow the error..
+                                       if(!args.Continue)
+                                               throw e;
+                               }
+                                table.EndLoadData ();
+                                counter++;
+                        }
+                        return counter;
+                }
+
 #endif // NET_2_0
 
                public override DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType) 
                {
-                       return FillSchema (dataSet, schemaType, SelectCommand, DefaultSourceTableName, CommandBehavior.Default);
+                       return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, DefaultSourceTableName, CommandBehavior.Default);
                }
 
                public DataTable FillSchema (DataTable dataTable, SchemaType schemaType) 
                {
-                       return FillSchema (dataTable, schemaType, SelectCommand, CommandBehavior.Default);
+                       return FillSchema (dataTable, schemaType, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
                }
 
                public DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, string srcTable) 
                {
-                       return FillSchema (dataSet, schemaType, SelectCommand, srcTable, CommandBehavior.Default);
+                       return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, srcTable, CommandBehavior.Default);
                }
 
-               [MonoTODO ("Verify")]
                protected virtual DataTable FillSchema (DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior) 
                {
+                       if (dataTable == null)
+                               throw new ArgumentNullException ("DataTable");
+
                        behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo;
                        if (command.Connection.State == ConnectionState.Closed) {
                                command.Connection.Open ();
@@ -450,7 +550,15 @@ namespace System.Data.Common {
                                string tableName =  SetupSchema (schemaType, dataTable.TableName);
                                if (tableName != null)
                                {
-                                       BuildSchema (reader, dataTable, schemaType);
+                                       // FillSchema should add the KeyInfo unless MissingSchemaAction
+                                       // is set to Ignore or Error.
+                                       MissingSchemaAction schemaAction = MissingSchemaAction;
+                                       if (!(schemaAction == MissingSchemaAction.Ignore ||
+                                               schemaAction == MissingSchemaAction.Error))
+                                               schemaAction = MissingSchemaAction.AddWithKey;
+
+                                       BuildSchema (reader, dataTable, schemaType, schemaAction,
+                                               MissingMappingAction, TableMappings);
                                }
                        }
                        finally
@@ -460,9 +568,11 @@ namespace System.Data.Common {
                        return dataTable;
                }
 
-               [MonoTODO ("Verify")]
                protected virtual DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior) 
                {
+                       if (dataSet == null)
+                               throw new ArgumentNullException ("DataSet");
+
                        behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo;
                        if (command.Connection.State == ConnectionState.Closed) {
                                command.Connection.Open ();
@@ -476,20 +586,33 @@ namespace System.Data.Common {
                        DataTable table;
                        try
                        {
-                               tableName = SetupSchema (schemaType, tableName);
-                               if (tableName != null)
-                               {
-                                       if (dataSet.Tables.Contains (tableName))
-                                               table = dataSet.Tables [tableName];     
-                                       else
+                               // FillSchema should add the KeyInfo unless MissingSchemaAction
+                               // is set to Ignore or Error.
+                               MissingSchemaAction schemaAction = MissingSchemaAction;
+                               if (!(MissingSchemaAction == MissingSchemaAction.Ignore ||
+                                       MissingSchemaAction == MissingSchemaAction.Error))
+                                       schemaAction = MissingSchemaAction.AddWithKey;
+
+                               do {
+                                       tableName = SetupSchema (schemaType, tableName);
+                                       if (tableName != null)
                                        {
-                                               table = new DataTable(tableName);
-                                               dataSet.Tables.Add (table);
+                                               if (dataSet.Tables.Contains (tableName))
+                                                       table = dataSet.Tables [tableName];     
+                                               else
+                                               {
+                                                       // Do not create schema if MissingSchemAction is set to Ignore
+                                                       if (this.MissingSchemaAction == MissingSchemaAction.Ignore)
+                                                               continue;
+                                                       table =  dataSet.Tables.Add (tableName);
+                                               }
+                                               
+                                               BuildSchema (reader, table, schemaType, schemaAction,
+                                                       MissingMappingAction, TableMappings);
+                                               output.Add (table);
+                                               tableName = String.Format ("{0}{1}", srcTable, ++index);
                                        }
-                                       BuildSchema (reader, table, schemaType);
-                                       output.Add (table);
-                                       tableName = String.Format ("{0}{1}", srcTable, ++index);
-                               }
+                               }while (reader.NextResult ());
                        }
                        finally
                        {
@@ -498,20 +621,6 @@ namespace System.Data.Common {
                        return (DataTable[]) output.ToArray (typeof (DataTable));
                }
 
-#if NET_2_0
-               [MonoTODO]
-               public DataSet GetDataSet ()
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public DataTable GetDataTable ()
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
                private string SetupSchema (SchemaType schemaType, string sourceTableName)
                {
                        DataTableMapping tableMapping = null;
@@ -519,7 +628,6 @@ namespace System.Data.Common {
                        if (schemaType == SchemaType.Mapped) 
                        {
                                tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, sourceTableName, sourceTableName, MissingMappingAction);
-
                                if (tableMapping != null)
                                        return tableMapping.DataSetTable;
                                return null;
@@ -531,7 +639,7 @@ namespace System.Data.Common {
                [EditorBrowsable (EditorBrowsableState.Advanced)]
                public override IDataParameter[] GetFillParameters () 
                {
-                       IDataParameter[] parameters = new IDataParameter[SelectCommand.Parameters.Count];
+                       IDataParameter[] parameters = new IDataParameter [SelectCommand.Parameters.Count];
                        SelectCommand.Parameters.CopyTo (parameters, 0);
                        return parameters;
                }
@@ -540,11 +648,10 @@ namespace System.Data.Common {
                // "array[ordinal of datatable column] == index of source column in data reader".
                // each column in the datatable has a mapping to a specific column in the datareader,
                // the int array represents this match.
-               [MonoTODO ("Test")]
                private int[] BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType)
                {
-                         return BuildSchema (reader, table, schemaType, MissingSchemaAction,
-                                             MissingMappingAction, TableMappings);
+                       return BuildSchema (reader, table, schemaType, MissingSchemaAction,
+                                           MissingMappingAction, TableMappings);
                 }
 
                 /// <summary>
@@ -558,7 +665,7 @@ namespace System.Data.Common {
                                                    MissingMappingAction missingMapAction,
                                                    DataTableMappingCollection dtMapping
                                                    )
-               {
+               {
                        int readerIndex = 0;
                        // FIXME : this fails if query has fewer columns than a table
                        int[] mapping = new int[table.Columns.Count]; // mapping the reader indexes to the datatable indexes
@@ -570,16 +677,30 @@ namespace System.Data.Common {
                        ArrayList primaryKey = new ArrayList ();
                        ArrayList sourceColumns = new ArrayList ();
                        bool createPrimaryKey = true;
-
-                       foreach (DataRow schemaRow in reader.GetSchemaTable ().Rows) {
+                       
+                       DataTable schemaTable = reader.GetSchemaTable ();
+
+                       DataColumn ColumnNameCol =  schemaTable.Columns["ColumnName"];
+                       DataColumn DataTypeCol = schemaTable.Columns["DataType"];
+                       DataColumn IsAutoIncrementCol = schemaTable.Columns["IsAutoIncrement"];
+                       DataColumn AllowDBNullCol = schemaTable.Columns["AllowDBNull"];
+                       DataColumn IsReadOnlyCol = schemaTable.Columns["IsReadOnly"];
+                       DataColumn IsKeyCol = schemaTable.Columns["IsKey"];
+                       DataColumn IsUniqueCol = schemaTable.Columns["IsUnique"];
+                       DataColumn ColumnSizeCol = schemaTable.Columns["ColumnSize"];
+
+                       foreach (DataRow schemaRow in schemaTable.Rows) {
                                // generate a unique column name in the source table.
                                string sourceColumnName;
-                               if (schemaRow.IsNull("ColumnName"))
+                               string realSourceColumnName ;
+                               if (ColumnNameCol == null || schemaRow.IsNull(ColumnNameCol) || (string)schemaRow [ColumnNameCol] == String.Empty) {
                                        sourceColumnName = DefaultSourceColumnName;
-                               else 
-                                       sourceColumnName = (string) schemaRow ["ColumnName"];
-
-                               string realSourceColumnName = sourceColumnName;
+                                       realSourceColumnName = DefaultSourceColumnName + "1";
+                               }
+                               else {
+                                       sourceColumnName = (string) schemaRow [ColumnNameCol];
+                                       realSourceColumnName = sourceColumnName;
+                               }
 
                                for (int i = 1; sourceColumns.Contains (realSourceColumnName); i += 1) 
                                        realSourceColumnName = String.Format ("{0}{1}", sourceColumnName, i);
@@ -588,21 +709,24 @@ namespace System.Data.Common {
                                // generate DataSetColumnName from DataTableMapping, if any
                                string dsColumnName = realSourceColumnName;
                                DataTableMapping tableMapping = null;
-                               tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (dtMapping, table.TableName, table.TableName, missingMapAction); 
-                               if (tableMapping != null) 
+
+                               //FIXME : The sourcetable name shud get passed as a parameter.. 
+                               int index = dtMapping.IndexOfDataSetTable (table.TableName);
+                               string srcTable = (index != -1 ? dtMapping[index].SourceTable : table.TableName);
+                               tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (dtMapping, srcTable, table.TableName, missingMapAction); 
+                               if (tableMapping != null)
                                {
-                                       
                                        table.TableName = tableMapping.DataSetTable;
                                        // check to see if the column mapping exists
                                        DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, missingMapAction);
                                        if (columnMapping != null)
                                        {
-                                               Type columnType = (Type)schemaRow["DataType"];
+                                               Type columnType = (Type)schemaRow[DataTypeCol];
                                                DataColumn col =
                                                        columnMapping.GetDataColumnBySchemaAction(
-                                                       table ,
-                                                       columnType,
-                                                       missingSchAction);
+                                                                                                 table ,
+                                                                                                 columnType,
+                                                                                                 missingSchAction);
 
                                                if (col != null)
                                                {
@@ -610,7 +734,7 @@ namespace System.Data.Common {
                                                        if (table.Columns.IndexOf(col) == -1)
                                                        {
                                                                if (missingSchAction == MissingSchemaAction.Add 
-                                                                       || missingSchAction == MissingSchemaAction.AddWithKey)
+                                                                   || missingSchAction == MissingSchemaAction.AddWithKey)
                                                                        table.Columns.Add(col);
 
                                                                int[] tmp = new int[mapping.Length + 1];
@@ -618,13 +742,26 @@ namespace System.Data.Common {
                                                                Array.Copy(mapping,col.Ordinal,tmp,col.Ordinal + 1,mapping.Length - col.Ordinal);
                                                                mapping = tmp;
                                                        }                               
-                                                       bool isAutoIncrement = (bool)schemaRow["IsAutoIncrement"];
-                                                       bool allowDBNull = (bool)schemaRow["AllowDBNull"];
-                                                       bool isReadOnly =(bool)schemaRow["IsReadOnly"];
-                                                       bool isKey = (bool)schemaRow["IsKey"];                                                  
-                                                       bool isUnique = (bool)schemaRow["IsUnique"];
 
-                            if (missingSchAction == MissingSchemaAction.AddWithKey) {
+
+                                                       if (missingSchAction == MissingSchemaAction.AddWithKey) {
+                                   
+                                                               object value = (AllowDBNullCol != null) ? schemaRow[AllowDBNullCol] : null;
+                                                               bool allowDBNull = value is bool ? (bool)value : true;
+
+                                                               value = (IsKeyCol != null) ? schemaRow[IsKeyCol] : null;
+                                                               bool isKey = value is bool ? (bool)value : false;
+
+                                                               value = (IsAutoIncrementCol != null) ? schemaRow[IsAutoIncrementCol] : null;
+                                                               bool isAutoIncrement = value is bool ? (bool)value : false;
+
+                                                               value = (IsReadOnlyCol != null) ? schemaRow[IsReadOnlyCol] : null;
+                                                               bool isReadOnly = value is bool ? (bool)value : false;
+
+                                                               value = (IsUniqueCol != null) ? schemaRow[IsUniqueCol] : null;
+                                                               bool isUnique = value is bool ? (bool)value : false;
+                                                               
+                                                               col.AllowDBNull = allowDBNull;
                                                                // fill woth key info                                                           
                                                                if (isAutoIncrement && DataColumn.CanAutoIncrement(columnType)) {
                                                                        col.AutoIncrement = true;
@@ -633,27 +770,33 @@ namespace System.Data.Common {
                                                                }
 
                                                                if (columnType == DbTypes.TypeOfString) {
-                                                                       col.MaxLength = (int)schemaRow["ColumnSize"];
+                                                                       col.MaxLength = (ColumnSizeCol != null) ? (int)schemaRow[ColumnSizeCol] : 0;
                                                                }
 
                                                                if (isReadOnly)
                                                                        col.ReadOnly = true;
-                                                       }
-                                                                                                                                                                       
-                                                       if (!allowDBNull && (!isReadOnly || isKey))
-                                                               col.AllowDBNull = false;
-                                                       if (isUnique && !isKey && !columnType.IsArray) {
-                                                               col.Unique = true;
-                                                               if (!allowDBNull)
+                                                                       
+                                                               if (!allowDBNull && (!isReadOnly || isKey))
                                                                        col.AllowDBNull = false;
-                                                       }
+                                                               if (isUnique && !isKey && !columnType.IsArray) {
+                                                                       col.Unique = true;
+                                                                       if (!allowDBNull)
+                                                                               col.AllowDBNull = false;
+                                                               }
+                                                               
+                                                               // This might not be set by all DataProviders
+                                                               bool isHidden = false;
+                                                               if (schemaTable.Columns.Contains ("IsHidden")) {
+                                                                       value = schemaRow["IsHidden"];
+                                                                       isHidden = ((value is bool) ? (bool)value : false);
+                                                               }
 
-                                                       if (isKey) {
-                                primaryKey.Add (col);
-                                                               if (allowDBNull)
-                                                                       createPrimaryKey = false;
-                            }
-                                                       
+                                                               if (isKey && !isHidden) {
+                                                                       primaryKey.Add (col);
+                                                                       if (allowDBNull)
+                                                                               createPrimaryKey = false;
+                                                               }
+                                                       }
                                                        // add the ordinal of the column as a key and the index of the column in the datareader as a value.
                                                        mapping[col.Ordinal] = readerIndex++;
                                                }
@@ -677,9 +820,7 @@ namespace System.Data.Common {
                                                table.Constraints.Add(uConstraint);
                                }
                        }
-
                        return mapping;
-                        
                 }
 
                [MonoTODO]
@@ -688,7 +829,6 @@ namespace System.Data.Common {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public int Update (DataRow[] dataRows) 
                {
                        if (dataRows == null)
@@ -711,9 +851,9 @@ namespace System.Data.Common {
                                        throw new ArgumentException("dataRows[" + i + "].");
                                if (dataRows[i].Table != table)
                                        throw new ArgumentException(
-                                               " DataRow["
-                                               + i
-                                               + "] is from a different DataTable than DataRow[0].");
+                                                                   " DataRow["
+                                                                   + i
+                                                                   + "] is from a different DataTable than DataRow[0].");
                        }
                        
                        // get table mapping for this rows
@@ -721,10 +861,10 @@ namespace System.Data.Common {
                        if (tableMapping == null)
                        {
                                tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction(
-                                       TableMappings,
-                                       table.TableName,
-                                       table.TableName,
-                                       MissingMappingAction);
+                                                                                                       TableMappings,
+                                                                                                       table.TableName,
+                                                                                                       table.TableName,
+                                                                                                       MissingMappingAction);
                                if (tableMapping != null) {
                                        foreach (DataColumn col in table.Columns) {
                                                if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0)
@@ -740,9 +880,9 @@ namespace System.Data.Common {
                                                cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName));
                                        tableMapping =
                                                new DataTableMapping (
-                                               table.TableName,
-                                               table.TableName,
-                                               cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
+                                                                     table.TableName,
+                                                                     table.TableName,
+                                                                     cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
                                }
                        }
 
@@ -758,20 +898,20 @@ namespace System.Data.Common {
 
                public int Update (DataTable dataTable) 
                {
-               /*
-                       int index = TableMappings.IndexOfDataSetTable (dataTable.TableName);
-                       if (index < 0)
-                               throw new ArgumentException ();
-                       return Update (dataTable, TableMappings [index]);
-               */
+                       /*
+                         int index = TableMappings.IndexOfDataSetTable (dataTable.TableName);
+                         if (index < 0)
+                         throw new ArgumentException ();
+                         return Update (dataTable, TableMappings [index]);
+                       */
                        DataTableMapping tableMapping = TableMappings.GetByDataSetTable (dataTable.TableName);
                        if (tableMapping == null)
                        {
                                tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (
-                                       TableMappings,
-                                       dataTable.TableName,
-                                       dataTable.TableName,
-                                       MissingMappingAction);
+                                                                                                        TableMappings,
+                                                                                                        dataTable.TableName,
+                                                                                                        dataTable.TableName,
+                                                                                                        MissingMappingAction);
                                if (tableMapping != null) {
                                        foreach (DataColumn col in dataTable.Columns) {
                                                if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0)
@@ -787,9 +927,9 @@ namespace System.Data.Common {
                                                cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName));
                                        tableMapping =
                                                new DataTableMapping (
-                                                       dataTable.TableName,
-                                                       dataTable.TableName,
-                                                       cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
+                                                                     dataTable.TableName,
+                                                                     dataTable.TableName,
+                                                                     cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []);
                                }
                        }
                        return Update (dataTable, tableMapping);
@@ -802,7 +942,6 @@ namespace System.Data.Common {
                        return Update (rows, tableMapping);
                }
 
-               [MonoTODO]
                protected virtual int Update (DataRow[] dataRows, DataTableMapping tableMapping) 
                {
                        int updateCount = 0;
@@ -814,17 +953,17 @@ namespace System.Data.Common {
                                switch (row.RowState) {
                                case DataRowState.Added:
                                        statementType = StatementType.Insert;
-                                       command = InsertCommand;
+                                       command = ((IDbDataAdapter) this).InsertCommand;
                                        commandName = "Insert";
                                        break;
                                case DataRowState.Deleted:
                                        statementType = StatementType.Delete;
-                                       command = DeleteCommand;
+                                       command = ((IDbDataAdapter) this).DeleteCommand;
                                        commandName = "Delete";
                                        break;
                                case DataRowState.Modified:
                                        statementType = StatementType.Update;
-                                       command = UpdateCommand;
+                                       command = ((IDbDataAdapter) this).UpdateCommand;
                                        commandName = "Update";
                                        break;
                                case DataRowState.Unchanged:
@@ -834,25 +973,54 @@ namespace System.Data.Common {
 
                                RowUpdatingEventArgs argsUpdating = CreateRowUpdatingEvent (row, command, statementType, tableMapping);
                                row.RowError = null;
+                               OnRowUpdating(argsUpdating);
+                               switch(argsUpdating.Status) {
+                               case UpdateStatus.Continue :
+                                       //continue in update operation
+                                       break;
+                               case UpdateStatus.ErrorsOccurred :
+                                       if (argsUpdating.Errors == null) {
+                                               argsUpdating.Errors = ExceptionHelper.RowUpdatedError();
+                                       }
+                                       row.RowError += argsUpdating.Errors.Message;
+                                       if (!ContinueUpdateOnError) {
+                                               throw argsUpdating.Errors;
+                                       }
+                                       continue;
+                               case UpdateStatus.SkipAllRemainingRows :
+                                       return updateCount;
+                               case UpdateStatus.SkipCurrentRow :
+                                       updateCount++;
+                                       continue;
+                               default :
+                                       throw ExceptionHelper.InvalidUpdateStatus(argsUpdating.Status);
+                               }
+                               command = argsUpdating.Command;                                 
                                try {
                                        if (command != null) {
                                                DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
+                                               IDataParameter nullCheckParam = null;
                                                foreach (IDataParameter parameter in command.Parameters) {
                                                        if ((parameter.Direction & ParameterDirection.Input) != 0) {
                                                                string dsColumnName = parameter.SourceColumn;
                                                                if (columnMappings.Contains(parameter.SourceColumn))
                                                                        dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
-                                                               if (dsColumnName == null || dsColumnName.Length <= 0)
-                                                                               continue;
-                                                               DataRowVersion rowVersion = DataRowVersion.Default;
+                                                               if (dsColumnName == null || dsColumnName.Length <= 0) {
+                                                                       nullCheckParam = parameter;
+                                                                       continue;
+                                                               }
 
+                                                               DataRowVersion rowVersion = parameter.SourceVersion;
                                                                // Parameter version is ignored for non-update commands
-                                                               if (statementType == StatementType.Update) 
-                                                                       rowVersion = parameter.SourceVersion;
                                                                if (statementType == StatementType.Delete) 
                                                                        rowVersion = DataRowVersion.Original;
 
                                                                parameter.Value = row [dsColumnName, rowVersion];
+                                                               if (nullCheckParam != null && (parameter.Value != null
+                                                                       && parameter.Value != DBNull.Value)) {
+                                                                       nullCheckParam.Value = 0;
+                                                                       nullCheckParam = null;
+                                                               }
                                                        }
                                                }
                                        }
@@ -862,39 +1030,15 @@ namespace System.Data.Common {
                                        argsUpdating.Status = UpdateStatus.ErrorsOccurred;
                                }
 
-                               OnRowUpdating(argsUpdating);
-
-                               switch(argsUpdating.Status) {
-                                       case UpdateStatus.Continue :
-                                               //continue in update operation
-                                               break;
-                                       case UpdateStatus.ErrorsOccurred :
-                                               if (argsUpdating.Errors == null) {
-                                                       argsUpdating.Errors = new DataException("RowUpdatedEvent: Errors occurred; no additional is information available.");
-                                               }
-                                               row.RowError += argsUpdating.Errors.Message;
-                                               if (!ContinueUpdateOnError) {
-                                                       throw argsUpdating.Errors;
-                                               }
-                                               continue;
-                                       case UpdateStatus.SkipAllRemainingRows :
-                                               return updateCount;
-                                       case UpdateStatus.SkipCurrentRow :
-                                               updateCount++;
-                                               continue;
-                                       default :
-                                               throw new ArgumentException(String.Format("Invalid UpdateStatus: {0}",argsUpdating.Status));
-                               }
-
-                               command = argsUpdating.Command;                                 
+                               
                                IDataReader reader = null;
                                try {                                                           
                                        if (command == null) {
-                                               throw new InvalidOperationException("ADP_UpdateRequiresCommand" + command);
+                                               throw ExceptionHelper.UpdateRequiresCommand(commandName);
                                        }                               
                                
                                        CommandBehavior commandBehavior = CommandBehavior.Default;
-                                               if (command.Connection.State == ConnectionState.Closed) {
+                                       if (command.Connection.State == ConnectionState.Closed) {
                                                command.Connection.Open ();
                                                commandBehavior |= CommandBehavior.CloseConnection;
                                        }
@@ -903,105 +1047,107 @@ namespace System.Data.Common {
                                        // so the connection will be closed if needed.
                                        reader = command.ExecuteReader (commandBehavior);
 
-                    // update the current row, if the update command returns any resultset
-                    // ignore other than the first record.
-                    DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
-
-                    if (command.UpdatedRowSource == UpdateRowSource.Both ||
-                        command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) {
-                            if (reader.Read ()){
-                                    DataTable retSchema = reader.GetSchemaTable ();
-                                    foreach (DataRow dr in retSchema.Rows) {
-                                        string columnName = dr ["ColumnName"].ToString ();
-                                        string dstColumnName = columnName;
-                                        if (columnMappings != null &&
-                                            columnMappings.Contains(columnName))
-                                                dstColumnName = columnMappings [dstColumnName].DataSetColumn;
-                                        DataColumn dstColumn = row.Table.Columns [dstColumnName];
-                                        if (dstColumn == null
-                                            || (dstColumn.Expression != null
-                                            && dstColumn.Expression.Length > 0))
-                                                continue;
-                                        // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/
-                                        // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx
-                                        // disable readonly for non-expression columns.
-                                        bool readOnlyState = dstColumn.ReadOnly;
-                                        dstColumn.ReadOnly = false;
-                                        try {
-                                                row [dstColumnName] = reader [columnName];
-                                        } finally {
-                                                dstColumn.ReadOnly = readOnlyState;
-                                        }                                    
-                                    }
-                            }
-                    }
-                    reader.Close ();
-
-                    int tmp = reader.RecordsAffected; // records affected is valid only after closing reader
+                                       // update the current row, if the update command returns any resultset
+                                       // ignore other than the first record.
+                                       DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
+
+                                       if (command.UpdatedRowSource == UpdateRowSource.Both ||
+                                           command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) {
+                                               if (reader.Read ()){
+                                                       DataTable retSchema = reader.GetSchemaTable ();
+                                                       foreach (DataRow dr in retSchema.Rows) {
+                                                               string columnName = dr ["ColumnName"].ToString ();
+                                                               string dstColumnName = columnName;
+                                                               if (columnMappings != null &&
+                                                                   columnMappings.Contains(columnName))
+                                                                       dstColumnName = columnMappings [dstColumnName].DataSetColumn;
+                                                               DataColumn dstColumn = row.Table.Columns [dstColumnName];
+                                                               if (dstColumn == null
+                                                                   || (dstColumn.Expression != null
+                                                                       && dstColumn.Expression.Length > 0))
+                                                                       continue;
+                                                               // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/
+                                                               // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx
+                                                               // disable readonly for non-expression columns.
+                                                               bool readOnlyState = dstColumn.ReadOnly;
+                                                               dstColumn.ReadOnly = false;
+                                                               try {
+                                                                       row [dstColumnName] = reader [columnName];
+                                                               } finally {
+                                                                       dstColumn.ReadOnly = readOnlyState;
+                                                               }                                    
+                                                       }
+                                               }
+                                       }
+                                       reader.Close ();
+
+                                       int tmp = reader.RecordsAffected; // records affected is valid only after closing reader
                                        // if the execute does not effect any rows we throw an exception.
                                        if (tmp == 0)
                                                throw new DBConcurrencyException("Concurrency violation: the " + 
                                                                                  commandName +"Command affected 0 records.");
                                        updateCount += tmp;
                                         
-                    if (command.UpdatedRowSource == UpdateRowSource.Both ||
-                        command.UpdatedRowSource == UpdateRowSource.OutputParameters) {
-                            // Update output parameters to row values
-                            foreach (IDataParameter parameter in command.Parameters) {
-                                    if (parameter.Direction != ParameterDirection.InputOutput
-                                        && parameter.Direction != ParameterDirection.Output
-                                        && parameter.Direction != ParameterDirection.ReturnValue)
-                                            continue;
-
-                                    string dsColumnName = parameter.SourceColumn;
-                                    if (columnMappings != null &&
-                                        columnMappings.Contains(parameter.SourceColumn))
-                                            dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
-                                    DataColumn dstColumn = row.Table.Columns [dsColumnName];
-                                    if (dstColumn == null
-                                        || (dstColumn.Expression != null 
-                                        && dstColumn.Expression.Length > 0))
-                                            continue;
-                                    bool readOnlyState = dstColumn.ReadOnly;
-                                    dstColumn.ReadOnly  = false;
-                                    try {
-                                            row [dsColumnName] = parameter.Value;
-                                    } finally {
-                                            dstColumn.ReadOnly = readOnlyState;
-                                    }
+                                       if (command.UpdatedRowSource == UpdateRowSource.Both ||
+                                           command.UpdatedRowSource == UpdateRowSource.OutputParameters) {
+                                               // Update output parameters to row values
+                                               foreach (IDataParameter parameter in command.Parameters) {
+                                                       if (parameter.Direction != ParameterDirection.InputOutput
+                                                           && parameter.Direction != ParameterDirection.Output
+                                                           && parameter.Direction != ParameterDirection.ReturnValue)
+                                                               continue;
+
+                                                       string dsColumnName = parameter.SourceColumn;
+                                                       if (columnMappings != null &&
+                                                           columnMappings.Contains(parameter.SourceColumn))
+                                                               dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
+                                                       DataColumn dstColumn = row.Table.Columns [dsColumnName];
+                                                       if (dstColumn == null
+                                                           || (dstColumn.Expression != null 
+                                                               && dstColumn.Expression.Length > 0))
+                                                               continue;
+                                                       bool readOnlyState = dstColumn.ReadOnly;
+                                                       dstColumn.ReadOnly  = false;
+                                                       try {
+                                                               row [dsColumnName] = parameter.Value;
+                                                       } finally {
+                                                               dstColumn.ReadOnly = readOnlyState;
+                                                       }
                                     
-                            }
-                    }
+                                               }
+                                       }
                     
-                    RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent(row, command, statementType, tableMapping);
-                    OnRowUpdated(updatedArgs);
-                    switch(updatedArgs.Status) {
-                    case UpdateStatus.Continue:
-                            break;
-                    case UpdateStatus.ErrorsOccurred:
-                            if (updatedArgs.Errors == null) {
-                                                               updatedArgs.Errors = new DataException("RowUpdatedEvent: Errors occurred; no additional is information available.");
-                                                       }
-                                                       row.RowError += updatedArgs.Errors.Message;
-                                                       if (!ContinueUpdateOnError) {
-                                                               throw updatedArgs.Errors;
-                                                       }
-                                                       break;
-                    case UpdateStatus.SkipCurrentRow:
-                            continue;
-                    case UpdateStatus.SkipAllRemainingRows:
-                            return updateCount;
-                    }
+                                       RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent(row, command, statementType, tableMapping);
+                                       OnRowUpdated(updatedArgs);
+                                       switch(updatedArgs.Status) {
+                                       case UpdateStatus.Continue:
+                                               break;
+                                       case UpdateStatus.ErrorsOccurred:
+                                               if (updatedArgs.Errors == null) {
+                                                       updatedArgs.Errors = ExceptionHelper.RowUpdatedError();
+                                               }
+                                               row.RowError += updatedArgs.Errors.Message;
+                                               if (!ContinueUpdateOnError) {
+                                                       throw updatedArgs.Errors;
+                                               }
+                                               break;
+                                       case UpdateStatus.SkipCurrentRow:
+                                               continue;
+                                       case UpdateStatus.SkipAllRemainingRows:
+                                               return updateCount;
+                                       }
+#if NET_2_0
+                                       if (!AcceptChangesDuringUpdate)
+                                               continue;
+#endif
                                        row.AcceptChanges ();
-                               }
-                               catch(Exception e) {
+                               } catch(Exception e) {
                                        row.RowError = e.Message;
                                        if (!ContinueUpdateOnError) {
                                                throw e;
                                        }
-                               }
-                               finally {
-                                       if (reader != null) {
+                               } finally {
+                                       if (reader != null && ! reader.IsClosed) {
                                                reader.Close ();
                                        }
                                }       
@@ -1012,16 +1158,53 @@ namespace System.Data.Common {
                public int Update (DataSet dataSet, string sourceTable) 
                {
                        MissingMappingAction mappingAction = MissingMappingAction;
+
                        if (mappingAction == MissingMappingAction.Ignore)
                                mappingAction = MissingMappingAction.Error;
+
                        DataTableMapping tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, sourceTable, sourceTable, mappingAction);
 
                        DataTable dataTable = dataSet.Tables[tableMapping.DataSetTable];
                        if (dataTable == null)
-                           throw new ArgumentException ("sourceTable");
-
+                               throw new ArgumentException (String.Format ("Missing table {0}",
+                                                                           sourceTable));
                        return Update (dataTable, tableMapping);
                }
+               
+#if NET_2_0
+               // All the batch methods, should be implemented, if supported,
+               // by individual providers 
+
+               protected virtual int AddToBatch (IDbCommand cmd)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual void ClearBatch ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual int ExecuteBatch ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual IDataParameter GetBatchedParameter (int commandIdentifier, int parameterIdentifer)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual void InitializeBatching ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual void TerminateBatching ()
+               {
+                       throw new NotSupportedException ();
+               }
+#endif
 
 #if ONLY_1_0 || ONLY_1_1
                protected virtual void OnFillError (FillErrorEventArgs value) 
@@ -1031,9 +1214,6 @@ namespace System.Data.Common {
                }
 #endif
 
-               protected abstract void OnRowUpdated (RowUpdatedEventArgs value);
-               protected abstract void OnRowUpdating (RowUpdatingEventArgs value);
-               
                #endregion // Methods
        }
 }