1 //------------------------------------------------------------------------------
2 // <copyright file="DataAdapter.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
9 namespace System.Data.Common {
12 using System.ComponentModel;
14 using System.Data.ProviderBase;
15 using System.Diagnostics;
16 using System.Globalization;
17 using System.Threading;
19 public class DataAdapter : Component, IDataAdapter { // V1.0.3300
21 static private readonly object EventFillError = new object();
23 private bool _acceptChangesDuringUpdate = true;
24 private bool _acceptChangesDuringUpdateAfterInsert = true;
25 private bool _continueUpdateOnError = false;
26 private bool _hasFillErrorHandler = false;
27 private bool _returnProviderSpecificTypes = false;
29 private bool _acceptChangesDuringFill = true;
30 private LoadOption _fillLoadOption;
32 private MissingMappingAction _missingMappingAction = System.Data.MissingMappingAction.Passthrough;
33 private MissingSchemaAction _missingSchemaAction = System.Data.MissingSchemaAction.Add;
34 private DataTableMappingCollection _tableMappings;
36 private static int _objectTypeCount; // Bid counter
37 internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
40 // if true, we are asserting that the caller has provided a select command
41 // which should not return an empty result set
42 private bool _debugHookNonEmptySelectCommand = false;
45 [Conditional("DEBUG")]
46 void AssertReaderHandleFieldCount(DataReaderContainer readerHandler) {
48 Debug.Assert(!_debugHookNonEmptySelectCommand || readerHandler.FieldCount > 0, "Scenario expects non-empty results but no fields reported by reader");
52 [Conditional("DEBUG")]
53 void AssertSchemaMapping(SchemaMapping mapping) {
55 if (_debugHookNonEmptySelectCommand) {
56 Debug.Assert(mapping != null && mapping.DataValues != null && mapping.DataTable != null, "Debug hook specifies that non-empty results are not expected");
61 protected DataAdapter() : base() { // V1.0.3300
62 GC.SuppressFinalize(this);
65 protected DataAdapter(DataAdapter from) : base() { // V1.1.3300
71 ResCategoryAttribute(Res.DataCategory_Fill),
72 ResDescriptionAttribute(Res.DataAdapter_AcceptChangesDuringFill),
74 public bool AcceptChangesDuringFill { // V1.0.3300
76 //Bid.Trace("<comm.DataAdapter.get_AcceptChangesDuringFill|API> %d#\n", ObjectID);
77 return _acceptChangesDuringFill;
80 _acceptChangesDuringFill = value;
81 //Bid.Trace("<comm.DataAdapter.set_AcceptChangesDuringFill|API> %d#, %d\n", ObjectID, value);
86 EditorBrowsableAttribute(EditorBrowsableState.Never)
88 virtual public bool ShouldSerializeAcceptChangesDuringFill() {
89 return (0 == _fillLoadOption);
94 ResCategoryAttribute(Res.DataCategory_Update),
95 ResDescriptionAttribute(Res.DataAdapter_AcceptChangesDuringUpdate),
97 public bool AcceptChangesDuringUpdate { // V1.2.3300, MDAC 74988
99 //Bid.Trace("<comm.DataAdapter.get_AcceptChangesDuringUpdate|API> %d#\n", ObjectID);
100 return _acceptChangesDuringUpdate;
103 _acceptChangesDuringUpdate = value;
104 //Bid.Trace("<comm.DataAdapter.set_AcceptChangesDuringUpdate|API> %d#, %d\n", ObjectID, value);
110 ResCategoryAttribute(Res.DataCategory_Update),
111 ResDescriptionAttribute(Res.DataAdapter_ContinueUpdateOnError),
113 public bool ContinueUpdateOnError { // V1.0.3300, MDAC 66900
115 //Bid.Trace("<comm.DataAdapter.get_ContinueUpdateOnError|API> %d#\n", ObjectID);
116 return _continueUpdateOnError;
119 _continueUpdateOnError = value;
120 //Bid.Trace("<comm.DataAdapter.set_ContinueUpdateOnError|API> %d#, %d\n", ObjectID, value);
125 RefreshProperties(RefreshProperties.All),
126 ResCategoryAttribute(Res.DataCategory_Fill),
127 ResDescriptionAttribute(Res.DataAdapter_FillLoadOption),
129 public LoadOption FillLoadOption { // V1.2.3300
131 //Bid.Trace("<comm.DataAdapter.get_FillLoadOption|API> %d#\n", ObjectID);
132 LoadOption fillLoadOption = _fillLoadOption;
133 return ((0 != fillLoadOption) ? _fillLoadOption : LoadOption.OverwriteChanges);
137 case 0: // to allow simple resetting
138 case LoadOption.OverwriteChanges:
139 case LoadOption.PreserveChanges:
140 case LoadOption.Upsert:
141 _fillLoadOption = value;
142 //Bid.Trace("<comm.DataAdapter.set_FillLoadOption|API> %d#, %d{ds.LoadOption}\n", ObjectID, (int)value);
145 throw ADP.InvalidLoadOption(value);
151 EditorBrowsableAttribute(EditorBrowsableState.Never)
153 public void ResetFillLoadOption() {
158 EditorBrowsableAttribute(EditorBrowsableState.Never)
160 virtual public bool ShouldSerializeFillLoadOption() {
161 return (0 != _fillLoadOption);
165 DefaultValue(System.Data.MissingMappingAction.Passthrough),
166 ResCategoryAttribute(Res.DataCategory_Mapping),
167 ResDescriptionAttribute(Res.DataAdapter_MissingMappingAction),
169 public MissingMappingAction MissingMappingAction { // V1.0.3300
171 //Bid.Trace("<comm.DataAdapter.get_MissingMappingAction|API> %d#\n", ObjectID);
172 return _missingMappingAction;
175 switch(value) { // @perfnote: Enum.IsDefined
176 case MissingMappingAction.Passthrough:
177 case MissingMappingAction.Ignore:
178 case MissingMappingAction.Error:
179 _missingMappingAction = value;
180 //Bid.Trace("<comm.DataAdapter.set_MissingMappingAction|API> %d#, %d{ds.MissingMappingAction}\n", ObjectID, (int)value);
183 throw ADP.InvalidMissingMappingAction(value);
189 DefaultValue(Data.MissingSchemaAction.Add),
190 ResCategoryAttribute(Res.DataCategory_Mapping),
191 ResDescriptionAttribute(Res.DataAdapter_MissingSchemaAction),
193 public MissingSchemaAction MissingSchemaAction { // V1.0.3300
195 //Bid.Trace("<comm.DataAdapter.get_MissingSchemaAction|API> %d#\n", ObjectID);
196 return _missingSchemaAction;
199 switch(value) { // @perfnote: Enum.IsDefined
200 case MissingSchemaAction.Add:
201 case MissingSchemaAction.Ignore:
202 case MissingSchemaAction.Error:
203 case MissingSchemaAction.AddWithKey:
204 _missingSchemaAction = value;
205 //Bid.Trace("<comm.DataAdapter.set_MissingSchemaAction|API> %d#, %d{MissingSchemaAction}\n", ObjectID, (int)value);
208 throw ADP.InvalidMissingSchemaAction(value);
213 internal int ObjectID {
221 ResCategoryAttribute(Res.DataCategory_Fill),
222 ResDescriptionAttribute(Res.DataAdapter_ReturnProviderSpecificTypes),
224 virtual public bool ReturnProviderSpecificTypes {
226 //Bid.Trace("<comm.DataAdapter.get_ReturnProviderSpecificTypes|API> %d#\n", ObjectID);
227 return _returnProviderSpecificTypes;
230 _returnProviderSpecificTypes = value;
231 //Bid.Trace("<comm.DataAdapter.set_ReturnProviderSpecificTypes|API> %d#, %d\n", ObjectID, (int)value);
236 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
237 ResCategoryAttribute(Res.DataCategory_Mapping),
238 ResDescriptionAttribute(Res.DataAdapter_TableMappings),
240 public DataTableMappingCollection TableMappings { // V1.0.3300
242 //Bid.Trace("<comm.DataAdapter.get_TableMappings|API> %d#\n", ObjectID);
243 DataTableMappingCollection mappings = _tableMappings;
244 if (null == mappings) {
245 mappings = CreateTableMappings();
246 if (null == mappings) {
247 mappings = new DataTableMappingCollection();
249 _tableMappings = mappings;
251 return mappings; // constructed by base class
255 ITableMappingCollection IDataAdapter.TableMappings { // V1.0.3300
257 return TableMappings;
261 virtual protected bool ShouldSerializeTableMappings() { // V1.0.3300, MDAC 65548
262 return true; /*HasTableMappings();*/ // VS7 300569
265 protected bool HasTableMappings() { // V1.2.3300
266 return ((null != _tableMappings) && (0 < TableMappings.Count));
270 ResCategoryAttribute(Res.DataCategory_Fill),
271 ResDescriptionAttribute(Res.DataAdapter_FillError),
273 public event FillErrorEventHandler FillError { // V1.2.3300, DbDataADapter V1.0.3300
275 _hasFillErrorHandler = true;
276 Events.AddHandler(EventFillError, value);
279 Events.RemoveHandler(EventFillError, value);
283 [ Obsolete("CloneInternals() has been deprecated. Use the DataAdapter(DataAdapter from) constructor. http://go.microsoft.com/fwlink/?linkid=14202") ] // V1.1.3300, MDAC 81448
284 [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] // MDAC 82936
285 virtual protected DataAdapter CloneInternals() { // V1.0.3300
286 DataAdapter clone = (DataAdapter)Activator.CreateInstance(GetType(), System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Instance, null, null, CultureInfo.InvariantCulture, null);
287 clone.CloneFrom(this);
291 private void CloneFrom(DataAdapter from) {
292 _acceptChangesDuringUpdate = from._acceptChangesDuringUpdate;
293 _acceptChangesDuringUpdateAfterInsert = from._acceptChangesDuringUpdateAfterInsert;
294 _continueUpdateOnError = from._continueUpdateOnError;
295 _returnProviderSpecificTypes = from._returnProviderSpecificTypes; // WebData 101795
296 _acceptChangesDuringFill = from._acceptChangesDuringFill;
297 _fillLoadOption = from._fillLoadOption;
298 _missingMappingAction = from._missingMappingAction;
299 _missingSchemaAction = from._missingSchemaAction;
301 if ((null != from._tableMappings) && (0 < from.TableMappings.Count)) {
302 DataTableMappingCollection parameters = this.TableMappings;
303 foreach(object parameter in from.TableMappings) {
304 parameters.Add((parameter is ICloneable) ? ((ICloneable)parameter).Clone() : parameter);
309 virtual protected DataTableMappingCollection CreateTableMappings() { // V1.0.3300
310 Bid.Trace("<comm.DataAdapter.CreateTableMappings|API> %d#\n", ObjectID);
311 return new DataTableMappingCollection();
314 override protected void Dispose(bool disposing) { // V1.0.3300, MDAC 65459
315 if (disposing) { // release mananged objects
316 _tableMappings = null;
318 // release unmanaged objects
320 base.Dispose(disposing); // notify base classes
323 virtual public DataTable[] FillSchema(DataSet dataSet, SchemaType schemaType) { // V1.0.3300
324 throw ADP.NotSupported();
327 virtual protected DataTable[] FillSchema(DataSet dataSet, SchemaType schemaType, string srcTable, IDataReader dataReader) { // V1.2.3300
329 Bid.ScopeEnter(out hscp, "<comm.DataAdapter.FillSchema|API> %d#, dataSet, schemaType=%d{ds.SchemaType}, srcTable, dataReader\n", ObjectID, (int)schemaType);
331 if (null == dataSet) {
332 throw ADP.ArgumentNull("dataSet");
334 if ((SchemaType.Source != schemaType) && (SchemaType.Mapped != schemaType)) {
335 throw ADP.InvalidSchemaType(schemaType);
337 if (ADP.IsEmpty(srcTable)) {
338 throw ADP.FillSchemaRequiresSourceTableName("srcTable");
340 if ((null == dataReader) || dataReader.IsClosed) {
341 throw ADP.FillRequires("dataReader");
343 // user must Close/Dispose of the dataReader
344 object value = FillSchemaFromReader(dataSet, null, schemaType, srcTable, dataReader);
345 return (DataTable[]) value;
348 Bid.ScopeLeave(ref hscp);
352 virtual protected DataTable FillSchema(DataTable dataTable, SchemaType schemaType, IDataReader dataReader) { // V1.2.3300
354 Bid.ScopeEnter(out hscp, "<comm.DataAdapter.FillSchema|API> %d#, dataTable, schemaType, dataReader\n", ObjectID);
356 if (null == dataTable) {
357 throw ADP.ArgumentNull("dataTable");
359 if ((SchemaType.Source != schemaType) && (SchemaType.Mapped != schemaType)) {
360 throw ADP.InvalidSchemaType(schemaType);
362 if ((null == dataReader) || dataReader.IsClosed) {
363 throw ADP.FillRequires("dataReader");
365 // user must Close/Dispose of the dataReader
366 // user will have to call NextResult to access remaining results
367 object value = FillSchemaFromReader(null, dataTable, schemaType, null, dataReader);
368 return (DataTable) value;
371 Bid.ScopeLeave(ref hscp);
375 internal object FillSchemaFromReader(DataSet dataset, DataTable datatable, SchemaType schemaType, string srcTable, IDataReader dataReader) {
376 DataTable[] dataTables = null;
379 DataReaderContainer readerHandler = DataReaderContainer.Create(dataReader, ReturnProviderSpecificTypes);
381 AssertReaderHandleFieldCount(readerHandler);
382 if (0 >= readerHandler.FieldCount) {
386 if (null != dataset) {
387 tmp = DataAdapter.GetSourceTableName(srcTable, schemaCount);
388 schemaCount++; // don't increment if no SchemaTable ( a non-row returning result )
391 SchemaMapping mapping = new SchemaMapping(this, dataset, datatable, readerHandler, true, schemaType, tmp, false, null, null);
393 if (null != datatable) {
394 // do not read remaining results in single DataTable case
395 return mapping.DataTable;
397 else if (null != mapping.DataTable) {
398 if (null == dataTables) {
399 dataTables = new DataTable[1] { mapping.DataTable };
402 dataTables = DataAdapter.AddDataTableToArray(dataTables, mapping.DataTable);
405 } while (dataReader.NextResult()); // FillSchema does not capture errors for FillError event
407 object value = dataTables;
408 if ((null == value) && (null == datatable)) { // WebData 101757
409 value = new DataTable[0];
411 return value; // null if datatable had no results
414 virtual public int Fill(DataSet dataSet) { // V1.0.3300
415 throw ADP.NotSupported();
418 virtual protected int Fill(DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) { // V1.2.3300, DbDataAdapter V1.0.3300
420 Bid.ScopeEnter(out hscp, "<comm.DataAdapter.Fill|API> %d#, dataSet, srcTable, dataReader, startRecord, maxRecords\n", ObjectID);
422 if (null == dataSet) {
423 throw ADP.FillRequires("dataSet");
425 if (ADP.IsEmpty(srcTable)) {
426 throw ADP.FillRequiresSourceTableName("srcTable");
428 if (null == dataReader) {
429 throw ADP.FillRequires("dataReader");
431 if (startRecord < 0) {
432 throw ADP.InvalidStartRecord("startRecord", startRecord);
434 if (maxRecords < 0) {
435 throw ADP.InvalidMaxRecords("maxRecords", maxRecords);
437 if (dataReader.IsClosed) {
440 // user must Close/Dispose of the dataReader
441 DataReaderContainer readerHandler = DataReaderContainer.Create(dataReader, ReturnProviderSpecificTypes);
442 return FillFromReader(dataSet, null, srcTable, readerHandler, startRecord, maxRecords, null, null);
445 Bid.ScopeLeave(ref hscp);
449 virtual protected int Fill(DataTable dataTable, IDataReader dataReader) { // V1.2.3300, DbDataADapter V1.0.3300
450 DataTable[] dataTables = new DataTable[] { dataTable };
451 return Fill(dataTables, dataReader, 0, 0);
454 virtual protected int Fill(DataTable[] dataTables, IDataReader dataReader, int startRecord, int maxRecords) { // V1.2.3300
456 Bid.ScopeEnter(out hscp, "<comm.DataAdapter.Fill|API> %d#, dataTables[], dataReader, startRecord, maxRecords\n", ObjectID);
458 ADP.CheckArgumentLength(dataTables, "tables");
459 if ((null == dataTables) || (0 == dataTables.Length) || (null == dataTables[0])) {
460 throw ADP.FillRequires("dataTable");
462 if (null == dataReader) {
463 throw ADP.FillRequires("dataReader");
465 if ((1 < dataTables.Length) && ((0 != startRecord) || (0 != maxRecords))) {
466 throw ADP.NotSupported(); // FillChildren is not supported with FillPage
470 bool enforceContraints = false;
471 DataSet commonDataSet = dataTables[0].DataSet;
473 if (null != commonDataSet) {
474 enforceContraints = commonDataSet.EnforceConstraints;
475 commonDataSet.EnforceConstraints = false;
477 for(int i = 0; i < dataTables.Length; ++i) {
478 Debug.Assert(null != dataTables[i], "null DataTable Fill");
480 if (dataReader.IsClosed) {
482 Debug.Assert(!_debugHookNonEmptySelectCommand, "Debug hook asserts data reader should be open");
486 DataReaderContainer readerHandler = DataReaderContainer.Create(dataReader, ReturnProviderSpecificTypes);
487 AssertReaderHandleFieldCount(readerHandler);
488 if (readerHandler.FieldCount <= 0) {
491 bool lastFillNextResult;
493 lastFillNextResult = FillNextResult(readerHandler);
495 while (lastFillNextResult && readerHandler.FieldCount <= 0);
496 if (!lastFillNextResult) {
504 if ((0 < i) && !FillNextResult(readerHandler)) {
507 // user must Close/Dispose of the dataReader
508 // user will have to call NextResult to access remaining results
509 int count = FillFromReader(null, dataTables[i], null, readerHandler, startRecord, maxRecords, null, null);
515 catch(ConstraintException) {
516 enforceContraints = false;
520 if (enforceContraints) {
521 commonDataSet.EnforceConstraints = true;
527 Bid.ScopeLeave(ref hscp);
531 internal int FillFromReader(DataSet dataset, DataTable datatable, string srcTable, DataReaderContainer dataReader, int startRecord, int maxRecords, DataColumn parentChapterColumn, object parentChapterValue) {
532 int rowsAddedToDataSet = 0;
535 AssertReaderHandleFieldCount(dataReader);
536 if (0 >= dataReader.FieldCount) {
537 continue; // loop to next result
540 SchemaMapping mapping = FillMapping(dataset, datatable, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue);
541 schemaCount++; // don't increment if no SchemaTable ( a non-row returning result )
543 AssertSchemaMapping(mapping);
545 if (null == mapping) {
546 continue; // loop to next result
548 if (null == mapping.DataValues) {
549 continue; // loop to next result
551 if (null == mapping.DataTable) {
552 continue; // loop to next result
554 mapping.DataTable.BeginLoadData();
556 // startRecord and maxRecords only apply to the first resultset
557 if ((1 == schemaCount) && ((0 < startRecord) || (0 < maxRecords))) {
558 rowsAddedToDataSet = FillLoadDataRowChunk(mapping, startRecord, maxRecords);
561 int count = FillLoadDataRow(mapping);
563 if (1 == schemaCount) { // MDAC 71347
564 // only return LoadDataRow count for first resultset
565 // not secondary or chaptered results
566 rowsAddedToDataSet = count;
571 mapping.DataTable.EndLoadData();
573 if (null != datatable) {
574 break; // do not read remaining results in single DataTable case
576 } while (FillNextResult(dataReader));
578 return rowsAddedToDataSet;
581 private int FillLoadDataRowChunk(SchemaMapping mapping, int startRecord, int maxRecords) {
582 DataReaderContainer dataReader = mapping.DataReader;
584 while (0 < startRecord) {
585 if (!dataReader.Read()) {
586 // there are no more rows on first resultset
592 int rowsAddedToDataSet = 0;
593 if (0 < maxRecords) {
594 while ((rowsAddedToDataSet < maxRecords) && dataReader.Read()) {
595 if (_hasFillErrorHandler) {
597 mapping.LoadDataRowWithClear();
598 rowsAddedToDataSet++;
602 if (!ADP.IsCatchableExceptionType(e)) {
605 ADP.TraceExceptionForCapture(e);
606 OnFillErrorHandler(e, mapping.DataTable, mapping.DataValues);
610 mapping.LoadDataRow();
611 rowsAddedToDataSet++;
614 // skip remaining rows of the first resultset
617 rowsAddedToDataSet = FillLoadDataRow(mapping);
619 return rowsAddedToDataSet;
622 private int FillLoadDataRow(SchemaMapping mapping) {
623 int rowsAddedToDataSet = 0;
624 DataReaderContainer dataReader = mapping.DataReader;
625 if (_hasFillErrorHandler) {
626 while (dataReader.Read()) { // read remaining rows of first and subsequent resultsets
628 // only try-catch if a FillErrorEventHandler is registered so that
629 // in the default case we get the full callstack from users
630 mapping.LoadDataRowWithClear();
631 rowsAddedToDataSet++;
635 if (!ADP.IsCatchableExceptionType(e)) {
638 ADP.TraceExceptionForCapture(e);
639 OnFillErrorHandler(e, mapping.DataTable, mapping.DataValues);
644 while (dataReader.Read()) { // read remaining rows of first and subsequent resultset
645 mapping.LoadDataRow();
646 rowsAddedToDataSet++;
649 return rowsAddedToDataSet;
652 private SchemaMapping FillMappingInternal(DataSet dataset, DataTable datatable, string srcTable, DataReaderContainer dataReader, int schemaCount, DataColumn parentChapterColumn, object parentChapterValue) {
653 bool withKeyInfo = (Data.MissingSchemaAction.AddWithKey == MissingSchemaAction);
655 if (null != dataset) {
656 tmp = DataAdapter.GetSourceTableName(srcTable, schemaCount);
658 return new SchemaMapping(this, dataset, datatable, dataReader, withKeyInfo, SchemaType.Mapped, tmp, true, parentChapterColumn, parentChapterValue);
661 private SchemaMapping FillMapping(DataSet dataset, DataTable datatable, string srcTable, DataReaderContainer dataReader, int schemaCount, DataColumn parentChapterColumn, object parentChapterValue) {
662 SchemaMapping mapping = null;
663 if (_hasFillErrorHandler) {
665 // only try-catch if a FillErrorEventHandler is registered so that
666 // in the default case we get the full callstack from users
667 mapping = FillMappingInternal(dataset, datatable, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue);
671 if (!ADP.IsCatchableExceptionType(e)) {
674 ADP.TraceExceptionForCapture(e);
675 OnFillErrorHandler(e, null, null);
679 mapping = FillMappingInternal(dataset, datatable, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue);
684 private bool FillNextResult(DataReaderContainer dataReader) {
686 if (_hasFillErrorHandler) {
688 // only try-catch if a FillErrorEventHandler is registered so that
689 // in the default case we get the full callstack from users
690 result = dataReader.NextResult();
694 if (!ADP.IsCatchableExceptionType(e)) {
697 ADP.TraceExceptionForCapture(e);
698 OnFillErrorHandler(e, null, null);
702 result = dataReader.NextResult();
707 [ EditorBrowsableAttribute(EditorBrowsableState.Advanced) ] // MDAC 69508
708 virtual public IDataParameter[] GetFillParameters() { // V1.0.3300
709 return new IDataParameter[0];
712 internal DataTableMapping GetTableMappingBySchemaAction(string sourceTableName, string dataSetTableName, MissingMappingAction mappingAction) {
713 return DataTableMappingCollection.GetTableMappingBySchemaAction(_tableMappings, sourceTableName, dataSetTableName, mappingAction);
716 internal int IndexOfDataSetTable(string dataSetTable) {
717 if (null != _tableMappings) {
718 return TableMappings.IndexOfDataSetTable(dataSetTable);
723 virtual protected void OnFillError(FillErrorEventArgs value) { // V1.2.3300, DbDataAdapter V1.0.3300
724 FillErrorEventHandler handler = (FillErrorEventHandler) Events[EventFillError];
725 if (null != handler) {
726 handler(this, value);
730 private void OnFillErrorHandler(Exception e, DataTable dataTable, object[] dataValues) {
731 FillErrorEventArgs fillErrorEvent = new FillErrorEventArgs(dataTable, dataValues);
732 fillErrorEvent.Errors = e;
733 OnFillError(fillErrorEvent);
735 if (!fillErrorEvent.Continue) {
736 if (null != fillErrorEvent.Errors) {
737 throw fillErrorEvent.Errors;
743 virtual public int Update(DataSet dataSet) { // V1.0.3300
744 throw ADP.NotSupported();
747 // used by FillSchema which returns an array of datatables added to the dataset
748 static private DataTable[] AddDataTableToArray(DataTable[] tables, DataTable newTable) {
749 for (int i = 0; i < tables.Length; ++i) { // search for duplicates
750 if (tables[i] == newTable) {
751 return tables; // duplicate found
754 DataTable[] newTables = new DataTable[tables.Length+1]; // add unique data table
755 for (int i = 0; i < tables.Length; ++i) {
756 newTables[i] = tables[i];
758 newTables[tables.Length] = newTable;
762 // dynamically generate source table names
763 static private string GetSourceTableName(string srcTable, int index) {
764 //if ((null != srcTable) && (0 <= index) && (index < srcTable.Length)) {
766 return srcTable; //[index];
768 return srcTable + index.ToString(System.Globalization.CultureInfo.InvariantCulture);
772 internal sealed class LoadAdapter : DataAdapter {
773 internal LoadAdapter() {
776 internal int FillFromReader(DataTable[] dataTables, IDataReader dataReader, int startRecord, int maxRecords) {
777 return Fill(dataTables, dataReader, startRecord, maxRecords);