Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / System.Data / System.Data.Common / DataAdapter.cs
1 //
2 // System.Data.Common.DataAdapter
3 //
4 // Author:
5 //   Rodrigo Moya (rodrigo@ximian.com)
6 //   Tim Coleman (tim@timcoleman.com)
7 //
8 // (C) Ximian, Inc
9 // Copyright (C) Tim Coleman, 2002-2003
10 //
11
12 //
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Data;
37 using System.Collections;
38 using System.ComponentModel;
39
40 namespace System.Data.Common
41 {
42         /// <summary>
43         /// Represents a set of data commands and a database connection that are used to fill the DataSet and update the data source.
44         /// </summary>
45         public
46 #if ONLY_1_1
47         abstract
48 #endif
49         class DataAdapter : Component, IDataAdapter
50         {
51                 #region Fields
52
53                 private bool acceptChangesDuringFill;
54                 private bool continueUpdateOnError;
55                 private MissingMappingAction missingMappingAction;
56                 private MissingSchemaAction missingSchemaAction;
57                 private DataTableMappingCollection tableMappings;
58                 private const string DefaultSourceTableName = "Table";
59                 private const string DefaultSourceColumnName = "Column";
60
61 #if NET_2_0
62                 private bool acceptChangesDuringUpdate;
63                 private LoadOption fillLoadOption;
64                 private bool returnProviderSpecificTypes;
65 #endif
66                 #endregion
67
68                 #region Constructors
69
70                 protected DataAdapter () 
71                 {
72                         acceptChangesDuringFill = true;
73                         continueUpdateOnError = false;
74                         missingMappingAction = MissingMappingAction.Passthrough;
75                         missingSchemaAction = MissingSchemaAction.Add;
76                         tableMappings = new DataTableMappingCollection ();
77 #if NET_2_0
78                         acceptChangesDuringUpdate = true;
79                         fillLoadOption = LoadOption.OverwriteChanges;
80                         returnProviderSpecificTypes = false;
81 #endif 
82                 }
83
84                 protected DataAdapter (DataAdapter from)
85                 {
86                         AcceptChangesDuringFill = from.AcceptChangesDuringFill;
87                         ContinueUpdateOnError = from.ContinueUpdateOnError;
88                         MissingMappingAction = from.MissingMappingAction;
89                         MissingSchemaAction = from.MissingSchemaAction;
90
91                         if (from.tableMappings != null)
92                                 foreach (ICloneable cloneable in from.TableMappings)
93                                         TableMappings.Add (cloneable.Clone ());
94 #if NET_2_0
95                         acceptChangesDuringUpdate = from.AcceptChangesDuringUpdate;
96                         fillLoadOption = from.FillLoadOption;
97                         returnProviderSpecificTypes = from.ReturnProviderSpecificTypes;
98 #endif 
99                 }
100
101                 #endregion
102
103                 #region Properties
104
105                 [DataCategory ("Fill")]
106 #if !NET_2_0
107                 [DataSysDescription ("Whether or not Fill will call DataRow.AcceptChanges.")]
108 #endif
109                 [DefaultValue (true)]
110                 public bool AcceptChangesDuringFill {
111                         get { return acceptChangesDuringFill; }
112                         set { acceptChangesDuringFill = value; }
113                 }
114
115 #if NET_2_0
116                 [DefaultValue (true)]
117                 public bool AcceptChangesDuringUpdate {
118                         get { return acceptChangesDuringUpdate; }
119                         set { acceptChangesDuringUpdate = value; }
120                 }
121 #endif
122
123                 [DataCategory ("Update")]
124 #if !NET_2_0
125                 [DataSysDescription ("Whether or not to continue to the next DataRow when the Update events, RowUpdating and RowUpdated, Status is UpdateStatus.ErrorsOccurred.")]
126 #endif
127                 [DefaultValue (false)]
128                 public bool ContinueUpdateOnError {
129                         get { return continueUpdateOnError; }
130                         set { continueUpdateOnError = value; }
131                 }
132
133 #if NET_2_0
134                 [RefreshProperties (RefreshProperties.All)]
135                 public LoadOption FillLoadOption {
136                         get { return fillLoadOption; }
137                         set {
138                                 ExceptionHelper.CheckEnumValue (typeof (LoadOption), value);
139                                 fillLoadOption = value;
140                 }
141                 }
142 #endif
143
144                 ITableMappingCollection IDataAdapter.TableMappings {
145                         get { return TableMappings; }
146                 }
147
148                 [DataCategory ("Mapping")]
149 #if !NET_2_0
150                 [DataSysDescription ("The action taken when a table or column in the TableMappings is missing.")]
151 #endif
152                 [DefaultValue (MissingMappingAction.Passthrough)]
153                 public MissingMappingAction MissingMappingAction {
154                         get { return missingMappingAction; }
155                         set {
156                                 ExceptionHelper.CheckEnumValue (typeof (MissingMappingAction), value);
157                                 missingMappingAction = value;
158                         }
159                 }
160
161                 [DataCategory ("Mapping")]
162 #if !NET_2_0
163                 [DataSysDescription ("The action taken when a table or column in the DataSet is missing.")]
164 #endif
165                 [DefaultValue (MissingSchemaAction.Add)]
166                 public MissingSchemaAction MissingSchemaAction {
167                         get { return missingSchemaAction; }
168                         set {
169                                 ExceptionHelper.CheckEnumValue (typeof (MissingSchemaAction), value);
170                                 missingSchemaAction = value; 
171                         }
172                 }
173
174 #if NET_2_0
175                 [DefaultValue (false)]
176                 public virtual bool ReturnProviderSpecificTypes {
177                         get { return returnProviderSpecificTypes; }
178                         set { returnProviderSpecificTypes = value; }
179                 }
180 #endif
181
182                 [DataCategory ("Mapping")]
183 #if !NET_2_0
184                 [DataSysDescription ("How to map source table to DataSet table.")]
185 #endif
186                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
187                 public DataTableMappingCollection TableMappings {
188                         get { return tableMappings; }
189                 }
190
191                 #endregion
192
193                 #region Events
194
195 #if NET_2_0
196                 public event FillErrorEventHandler FillError;
197 #endif
198
199                 #endregion
200
201                 #region Methods
202
203 #if !ONLY_1_0
204                 [Obsolete ("Use the protected constructor instead", false)]
205 #endif
206                 [MonoTODO]
207                 protected virtual DataAdapter CloneInternals ()
208                 {
209                         throw new NotImplementedException ();
210                 }
211
212                 protected virtual DataTableMappingCollection CreateTableMappings ()
213                 {
214                         return new DataTableMappingCollection ();
215                 }
216
217                 [MonoTODO]
218                 protected override void Dispose (bool disposing)
219                 {
220                         throw new NotImplementedException ();
221                 }
222
223                 protected virtual bool ShouldSerializeTableMappings ()
224                 {
225                         return true;
226                 }
227
228
229                 internal int FillInternal (DataTable dataTable, IDataReader dataReader)
230                 {
231                         if (dataReader.FieldCount == 0) {
232                                 dataReader.Close ();
233                                 return 0;
234                         }
235                         
236                         int count = 0;
237
238                         try {
239                                 string tableName = SetupSchema (SchemaType.Mapped, dataTable.TableName);
240                                 if (tableName != null) {
241                                         dataTable.TableName = tableName;
242                                         FillTable (dataTable, dataReader, 0, 0, ref count);
243                                 }
244                         } finally {
245                                 dataReader.Close ();
246                         }
247
248                         return count;
249                 }
250
251                 // this method builds the schema for a given datatable. it returns a int array with 
252                 // "array[ordinal of datatable column] == index of source column in data reader".
253                 // each column in the datatable has a mapping to a specific column in the datareader,
254                 // the int array represents this match.
255                 internal int[] BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType)
256                 {
257                         return BuildSchema (reader, table, schemaType, MissingSchemaAction,
258                                             MissingMappingAction, TableMappings);
259                 }
260
261                 /// <summary>
262                 ///     Creates or Modifies the schema of the given DataTable based on the schema of
263                 ///     the reader and the arguments passed.
264                 /// </summary>
265                 internal static int[] BuildSchema (IDataReader reader, DataTable table,
266                                                    SchemaType schemaType,
267                                                    MissingSchemaAction missingSchAction,
268                                                    MissingMappingAction missingMapAction,
269                                                    DataTableMappingCollection dtMapping
270                                                    )
271                 {
272                         int readerIndex = 0;
273                         // FIXME : this fails if query has fewer columns than a table
274                         int[] mapping = new int[table.Columns.Count]; // mapping the reader indexes to the datatable indexes
275                         
276                         for(int i=0; i < mapping.Length; i++) {
277                                 mapping[i] = -1;
278                         }
279                         
280                         ArrayList primaryKey = new ArrayList ();
281                         ArrayList sourceColumns = new ArrayList ();
282                         bool createPrimaryKey = true;
283                         
284                         DataTable schemaTable = reader.GetSchemaTable ();
285
286                         DataColumn ColumnNameCol =  schemaTable.Columns["ColumnName"];
287                         DataColumn DataTypeCol = schemaTable.Columns["DataType"];
288                         DataColumn IsAutoIncrementCol = schemaTable.Columns["IsAutoIncrement"];
289                         DataColumn AllowDBNullCol = schemaTable.Columns["AllowDBNull"];
290                         DataColumn IsReadOnlyCol = schemaTable.Columns["IsReadOnly"];
291                         DataColumn IsKeyCol = schemaTable.Columns["IsKey"];
292                         DataColumn IsUniqueCol = schemaTable.Columns["IsUnique"];
293                         DataColumn ColumnSizeCol = schemaTable.Columns["ColumnSize"];
294
295                         foreach (DataRow schemaRow in schemaTable.Rows) {
296                                 // generate a unique column name in the source table.
297                                 string sourceColumnName;
298                                 string realSourceColumnName ;
299                                 if (ColumnNameCol == null || schemaRow.IsNull(ColumnNameCol) ||
300                                     (string)schemaRow [ColumnNameCol] == String.Empty) {
301                                         sourceColumnName = DefaultSourceColumnName;
302                                         realSourceColumnName = DefaultSourceColumnName + "1";
303                                 } else {
304                                         sourceColumnName = (string) schemaRow [ColumnNameCol];
305                                         realSourceColumnName = sourceColumnName;
306                                 }
307
308                                 for (int i = 1; sourceColumns.Contains (realSourceColumnName); i += 1)
309                                         realSourceColumnName = String.Format ("{0}{1}", sourceColumnName, i);
310                                 sourceColumns.Add(realSourceColumnName);
311
312                                 // generate DataSetColumnName from DataTableMapping, if any
313                                 DataTableMapping tableMapping = null;
314
315                                 //FIXME : The sourcetable name shud get passed as a parameter.. 
316                                 int index = dtMapping.IndexOfDataSetTable (table.TableName);
317                                 string srcTable = (index != -1 ? dtMapping[index].SourceTable : table.TableName);
318                                 tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (dtMapping, srcTable, table.TableName, missingMapAction); 
319                                 if (tableMapping != null) {
320                                         table.TableName = tableMapping.DataSetTable;
321                                         // check to see if the column mapping exists
322                                         DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, missingMapAction);
323                                         if (columnMapping != null) {
324                                                 Type columnType = schemaRow[DataTypeCol] as Type;
325                                                 DataColumn col = columnType != null ? columnMapping.GetDataColumnBySchemaAction(
326                                                                                                                                 table ,
327                                                                                                                                 columnType,
328                                                                                                                                 missingSchAction) : null;
329
330                                                 if (col != null) {
331                                                         // if the column is not in the table - add it.
332                                                         if (table.Columns.IndexOf(col) == -1) {
333                                                                 if (missingSchAction == MissingSchemaAction.Add 
334                                                                     || missingSchAction == MissingSchemaAction.AddWithKey)
335                                                                         table.Columns.Add(col);
336
337                                                                 int[] tmp = new int[mapping.Length + 1];
338                                                                 Array.Copy(mapping,0,tmp,0,col.Ordinal);
339                                                                 Array.Copy(mapping,col.Ordinal,tmp,col.Ordinal + 1,mapping.Length - col.Ordinal);
340                                                                 mapping = tmp;
341                                                         }
342
343                                                         if (missingSchAction == MissingSchemaAction.AddWithKey) {
344                                                                 object value = (AllowDBNullCol != null) ? schemaRow[AllowDBNullCol] : null;
345                                                                 bool allowDBNull = value is bool ? (bool)value : true;
346
347                                                                 value = (IsKeyCol != null) ? schemaRow[IsKeyCol] : null;
348                                                                 bool isKey = value is bool ? (bool)value : false;
349
350                                                                 value = (IsAutoIncrementCol != null) ? schemaRow[IsAutoIncrementCol] : null;
351                                                                 bool isAutoIncrement = value is bool ? (bool)value : false;
352
353                                                                 value = (IsReadOnlyCol != null) ? schemaRow[IsReadOnlyCol] : null;
354                                                                 bool isReadOnly = value is bool ? (bool)value : false;
355
356                                                                 value = (IsUniqueCol != null) ? schemaRow[IsUniqueCol] : null;
357                                                                 bool isUnique = value is bool ? (bool)value : false;
358                                                                 
359                                                                 col.AllowDBNull = allowDBNull;
360                                                                 // fill woth key info
361                                                                 if (isAutoIncrement && DataColumn.CanAutoIncrement(columnType)) {
362                                                                         col.AutoIncrement = true;
363                                                                         if (!allowDBNull)
364                                                                                 col.AllowDBNull = false;
365                                                                 }
366
367                                                                 if (columnType == DbTypes.TypeOfString) {
368                                                                         col.MaxLength = (ColumnSizeCol != null) ? (int)schemaRow[ColumnSizeCol] : 0;
369                                                                 }
370
371                                                                 if (isReadOnly)
372                                                                         col.ReadOnly = true;
373                                                                         
374                                                                 if (!allowDBNull && (!isReadOnly || isKey))
375                                                                         col.AllowDBNull = false;
376                                                                 if (isUnique && !isKey && !columnType.IsArray) {
377                                                                         col.Unique = true;
378                                                                         if (!allowDBNull)
379                                                                                 col.AllowDBNull = false;
380                                                                 }
381                                                                 
382                                                                 // This might not be set by all DataProviders
383                                                                 bool isHidden = false;
384                                                                 if (schemaTable.Columns.Contains ("IsHidden")) {
385                                                                         value = schemaRow["IsHidden"];
386                                                                         isHidden = ((value is bool) ? (bool)value : false);
387                                                                 }
388
389                                                                 if (isKey && !isHidden) {
390                                                                         primaryKey.Add (col);
391                                                                         if (allowDBNull)
392                                                                                 createPrimaryKey = false;
393                                                                 }
394                                                         }
395                                                         // add the ordinal of the column as a key and the index of the column in the datareader as a value.
396                                                         mapping[col.Ordinal] = readerIndex++;
397                                                 }
398                                         }
399                                 }
400                         }
401                         if (primaryKey.Count > 0) {
402                                 DataColumn[] colKey = (DataColumn[])(primaryKey.ToArray(typeof (DataColumn)));
403                                 if (createPrimaryKey)
404                                         table.PrimaryKey = colKey;
405                                 else {
406                                         UniqueConstraint uConstraint = new UniqueConstraint(colKey);
407                                         for (int i = 0; i < table.Constraints.Count; i++) {
408                                                 if (table.Constraints[i].Equals(uConstraint)) {
409                                                         uConstraint = null;
410                                                         break;
411                                                 }
412                                         }
413
414                                         if (uConstraint != null)
415                                                 table.Constraints.Add(uConstraint);
416                                 }
417                         }
418                         return mapping;
419                 }
420
421                 internal bool FillTable (DataTable dataTable, IDataReader dataReader, int startRecord, int maxRecords, ref int counter)
422                 {
423                         if (dataReader.FieldCount == 0)
424                                 return false;
425
426                         int counterStart = counter;
427
428                         int[] mapping = BuildSchema (dataReader, dataTable, SchemaType.Mapped);
429                         
430                         int [] sortedMapping = new int [mapping.Length];
431                         int length = sortedMapping.Length;
432                         for (int i = 0; i < sortedMapping.Length; i++) {
433                                 if (mapping [i] >= 0)
434                                         sortedMapping [mapping [i]] = i;
435                                 else
436                                         sortedMapping [--length] = i;
437                         }
438
439                         for (int i = 0; i < startRecord; i++) {
440                                 dataReader.Read ();
441                         }
442
443                         dataTable.BeginLoadData ();
444                         while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) {
445                                 try {
446                                         dataTable.LoadDataRow (dataReader, sortedMapping, length, AcceptChangesDuringFill);
447                                         counter++;
448                                 }
449                                 catch (Exception e) {
450                                         object[] readerArray = new object [dataReader.FieldCount];
451                                         object[] tableArray = new object [mapping.Length];
452                                         // we get the values from the datareader
453                                         dataReader.GetValues (readerArray);
454                                         // copy from datareader columns to table columns according to given mapping
455                                         for (int i = 0; i < mapping.Length; i++) {
456                                                 if (mapping [i] >= 0) {
457                                                         tableArray [i] = readerArray [mapping [i]];
458                                                 }
459                                         }
460                                         FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e);
461                                         OnFillErrorInternal (args);
462
463                                         // if args.Continue is not set to true or if a handler is not set, rethrow the error..
464                                         if(!args.Continue)
465                                                 throw e;
466                                 }
467                         }
468                         dataTable.EndLoadData ();
469                         return true;
470                 }
471
472                 internal virtual void OnFillErrorInternal (FillErrorEventArgs value)
473                 {
474 #if NET_2_0
475                         OnFillError (value);
476 #endif
477                 }
478
479                 internal FillErrorEventArgs CreateFillErrorEvent (DataTable dataTable, object[] values, Exception e)
480                 {
481                         FillErrorEventArgs args = new FillErrorEventArgs (dataTable, values);
482                         args.Errors = e;
483                         args.Continue = false;
484                         return args;
485                 }
486
487                 internal string SetupSchema (SchemaType schemaType, string sourceTableName)
488                 {
489                         DataTableMapping tableMapping = null;
490
491                         if (schemaType == SchemaType.Mapped) {
492                                 tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, sourceTableName, sourceTableName, MissingMappingAction);
493                                 if (tableMapping != null)
494                                         return tableMapping.DataSetTable;
495                                 return null;
496                         } else
497                                 return sourceTableName;
498                 }
499
500                 internal int FillInternal (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords)
501                 {
502                         if (dataSet == null)
503                                 throw new ArgumentNullException ("DataSet");
504
505                         if (startRecord < 0)
506                                 throw new ArgumentException ("The startRecord parameter was less than 0.");
507                         if (maxRecords < 0)
508                                 throw new ArgumentException ("The maxRecords parameter was less than 0.");
509
510                         DataTable dataTable = null;
511                         int resultIndex = 0;
512                         int count = 0;
513                         
514                         try {
515                                 string tableName = srcTable;
516                                 do {
517                                         // Non-resultset queries like insert, delete or update aren't processed.
518                                         if (dataReader.FieldCount != -1) {
519                                                 tableName = SetupSchema (SchemaType.Mapped, tableName);
520                                                 if (tableName != null) {
521                                                         
522                                                         // check if the table exists in the dataset
523                                                         if (dataSet.Tables.Contains (tableName))
524                                                                 // get the table from the dataset
525                                                                 dataTable = dataSet.Tables [tableName];
526                                                         else {
527                                                                 // Do not create schema if MissingSchemAction is set to Ignore
528                                                                 if (this.MissingSchemaAction == MissingSchemaAction.Ignore)
529                                                                         continue;
530                                                                 dataTable = dataSet.Tables.Add (tableName);
531                                                         }
532         
533                                                         if (!FillTable (dataTable, dataReader, startRecord, maxRecords, ref count))
534                                                                 continue;
535         
536                                                         tableName = String.Format ("{0}{1}", srcTable, ++resultIndex);
537         
538                                                         startRecord = 0;
539                                                         maxRecords = 0;
540                                                 }
541                                         }
542                                 } while (dataReader.NextResult ());
543                         } finally {
544                                 dataReader.Close ();
545                         }
546
547                         return count;
548                 }
549
550 #if NET_2_0
551                 public virtual int Fill (DataSet dataSet)
552                 {
553                         throw new NotSupportedException();
554                 }
555
556                 protected virtual int Fill (DataTable dataTable, IDataReader dataReader)
557                 {
558                         return FillInternal (dataTable, dataReader);
559                 }
560
561                 protected virtual int Fill (DataTable[] dataTables, IDataReader dataReader, int startRecord, int maxRecords)
562                 {
563                         int count = 0;
564                         if (dataReader.IsClosed)
565                                 return 0;
566
567                         if (startRecord < 0)
568                                 throw new ArgumentException ("The startRecord parameter was less than 0.");
569                         if (maxRecords < 0)
570                                 throw new ArgumentException ("The maxRecords parameter was less than 0.");
571
572                         try {
573                                 foreach (DataTable dataTable in dataTables) {
574                                         string tableName = SetupSchema (SchemaType.Mapped, dataTable.TableName);
575                                         if (tableName != null) {
576                                                 dataTable.TableName = tableName;
577                                                 FillTable (dataTable, dataReader, 0, 0, ref count);
578                                         }
579                                 }
580                         } finally {
581                                 dataReader.Close ();
582                         }
583
584                         return count;
585                 }
586
587                 protected virtual int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords)
588                 {
589                         return FillInternal (dataSet, srcTable, dataReader, startRecord, maxRecords);
590                 }
591
592                 [MonoTODO]
593                 protected virtual DataTable FillSchema (DataTable dataTable, SchemaType schemaType, IDataReader dataReader)
594                 {
595                         throw new NotImplementedException ();
596                 }
597
598                 [MonoTODO]
599                 protected virtual DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, string srcTable, IDataReader dataReader)
600                 {
601                         throw new NotImplementedException ();
602                 }
603
604                 public virtual DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType)
605                 {
606                         throw new NotSupportedException ();
607                 }
608
609                 [MonoTODO]
610                 [EditorBrowsable (EditorBrowsableState.Advanced)]
611                 public virtual IDataParameter[] GetFillParameters ()
612                 {
613                         throw new NotImplementedException ();
614                 }
615
616                 protected bool HasTableMappings ()
617                 {
618                         return (TableMappings.Count != 0);
619                 }
620
621                 protected virtual void OnFillError (FillErrorEventArgs value)
622                 {
623                         if (FillError != null)
624                                 FillError (this, value);
625                 }
626
627                 [EditorBrowsable (EditorBrowsableState.Never)]
628                 public void ResetFillLoadOption ()
629                 {
630                         //FIXME: what else ??
631                         FillLoadOption = LoadOption.OverwriteChanges;
632                 }
633
634                 [EditorBrowsable (EditorBrowsableState.Never)]
635                 public virtual bool ShouldSerializeAcceptChangesDuringFill ()
636                 {
637                         return true;
638                 }
639
640                 [EditorBrowsable (EditorBrowsableState.Never)]
641                 public virtual bool ShouldSerializeFillLoadOption ()
642                 {
643                         return false;
644                 }
645
646                 [MonoTODO]
647                 public virtual int Update (DataSet dataSet)
648                 {
649                         throw new NotImplementedException ();
650                 }
651 #else
652                 public abstract int Fill (DataSet dataSet);
653                 public abstract DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType);
654                 public abstract IDataParameter[] GetFillParameters ();
655                 public abstract int Update (DataSet dataSet);
656 #endif
657
658                 #endregion
659                 
660         }
661 }