Good day. I am trying to load data received from the database through an ADO.NET 3-rd component, which does not have a DataReader.Fill method in the DataReader. Here is the actual code:

DataSet set = new DataSet(e.Node.Tag.ToString()); set.EnforceConstraints = false; set.Load(reader, LoadOption.PreserveChanges, ""); 

And sometimes, on some tables with time, it starts to fall into exceptions on the DataSet.Load method:

 Exception.Message: Невозможно удалить этот столбец, т.к. он является частью ограничения Constraint38 для таблицы Table1. Exception.StackTrace: в System.Data.DataColumnCollection.CanRemove(DataColumn column, Boolean fThrowException) в System.Data.DataColumnCollection.BaseRemove(DataColumn column) в System.Data.DataColumnCollection.Remove(DataColumn column) в System.Data.ProviderBase.SchemaMapping.RollbackAddedItems(List`1 items) в System.Data.ProviderBase.SchemaMapping.SetupSchemaWithKeyInfo(MissingMappingAction mappingAction, MissingSchemaAction schemaAction, Boolean gettingData, DataColumn parentChapterColumn, Object chapterValue) в System.Data.ProviderBase.SchemaMapping..ctor(DataAdapter adapter, DataSet dataset, DataTable datatable, DataReaderContainer dataReader, Boolean keyInfo, SchemaType schemaType, String sourceTableName, Boolean gettingData, DataColumn parentChapterColumn, Object parentChapterValue) в System.Data.Common.DataAdapter.FillMappingInternal(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue) в System.Data.Common.DataAdapter.FillMapping(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue) в System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue) в System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords) в System.Data.Common.LoadAdapter.FillFromReader(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords) в System.Data.DataSet.Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler, DataTable[] tables) в System.Data.DataSet.Load(IDataReader reader, LoadOption loadOption, String[] tables) 

It seems like I turned off the check on the uniqueness of the keys, but still there is some kind of check on the Constraints of keys and indexes.


The problem turned out to be in System.Data.DataKey - it has built-in restrictions for 32 columns, and throws exceptions if there are more of them (in my case there are 38 of them). The only solution to this problem that I found is to write a wrapper for the DataReader, and delete all primary and unique keys when returning them to DataReader.GetSchemaTable ().

  • Accumulate statistics if the problem most likely falls off in the settings of the DB - Alexsandr Ter

2 answers 2

In general, I found a place in System.Data where exceptions occur:

 if (this.table.DataSet != null) { ParentForeignKeyConstraintEnumerator parentForeignKeyConstraintEnumerator = new ParentForeignKeyConstraintEnumerator(this.table.DataSet, this.table); while (parentForeignKeyConstraintEnumerator.GetNext()) { Constraint constraint = parentForeignKeyConstraintEnumerator.GetConstraint(); if (!((ForeignKeyConstraint)constraint).ParentKey.ContainsColumn(column)) { continue; } if (fThrowException) { throw ExceptionBuilder.CannotRemoveConstraint(constraint.ConstraintName, constraint.Table.TableName); // <===== вот тут выкидывается исключения } return false; } } 

This is some kind of internal framework bug, they would at least check for this.table.DataSet.EnforceConstraints != false before throwing exceptions. You'll have to write your wrapper for the DataReader and, when getting the schema through GetSchemaTable (), clean all Constraint.

  • No, this is not a framework bug. EnforceConstraints is a setting that relates to data, not a schema. - Pavel Mayorov

A real exception occurs somewhere in the try block, after which it is caught in the catch block :

  try { // много кода } catch (Exception e) { if (ADP.IsCatchableOrSecurityExceptionType(e)) { RollbackAddedItems(addedItems); } throw; } 

Unfortunately, in the course of processing an exception, another exception arises, which causes the original exception to be lost.

It makes sense to enable debugging of the system libraries , then put a breakpoint inside this catch block and try to catch the error.

  • No, exceptions occur exactly in the place that I described - they throw it out themselves. What for that goes check Constraint-ov in DataSet and its tables. For a hint about debugging exceptions in the system libraries - thanks, now I'll try. - DeusExMachine
  • @DeusExMachine the place that you described is called from RollbackAddedItems (see stack). - Pavel Mayorov
  • Yes, you are right, you have reached the place that you described, here's what is in the exception there: "The number of columns cannot exceed 32." Probably some limitations of the 3-rd ADO.NET component will have to be looked at. - DeusExMachine pm