PC Review
Forums
Newsgroups
Microsoft DotNet
Microsoft ADO .NET
"Index was out of range" error when editing DataRow
Forums
Newsgroups
Microsoft DotNet
Microsoft ADO .NET
"Index was out of range" error when editing DataRow
![]() |
"Index was out of range" error when editing DataRow |
|
|
Thread Tools | Rate Thread |
|
|
#1 |
|
Guest
Posts: n/a
|
"Index was out of range" error when editing DataRow
Our application makes thousands of edits to DataSets without problem, but occasionally this error appears: "Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index" I have found one place in the code where I can reproduce the error, though still intermittently. In this case I am changing the value of field in a DataRow. This field happens to be a foreign key to a parent table. The parent table contains "Incidents" and the child table contains "Devices", and they are related through an "Incident ID". Here is the code that fails occasionally: deviceRow["INCIDENT_ID"] = newIncidentID; My testing indicates that the column name and value are valid. As the stack trace of the error shows, the problem instead has to do with changing the row state during the edit: Exception: System.ArgumentOutOfRangeException Message: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index Source: mscorlib at System.Collections.ArrayList.get_Item(Int32 index) at System.Data.DataTable.RecordStateChanged(Int32 record1, DataViewRowState oldState1, DataViewRowState newState1, Int32 record2, DataViewRowState oldState2, DataViewRowState newState2) at System.Data.DataTable.SetNewRecord(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge) at System.Data.DataRow.EndEdit() at System.Data.DataRow.set_Item(DataColumn column, Object value) at System.Data.DataRow.set_Item(String columnName, Object value) Any ideas on what could be causing this? Thanks, Jon Fairchild |
|
|
|
#2 |
|
Guest
Posts: n/a
|
Hi Jon:
Could you post the code block around it? There could be a few things going on but changing rowstate happens whenver you edit, I don't think that's the problem. If it works most of the time, I'm wondering if you aren't calling ..Remove or something like that which could be throwing off your counter loop or something. I can't really tell from this and although the stack trace is usually helpful, I can't see much there. Let me know and I'll see what I can come up with. Cheers, Bill -- W.G. Ryan MVP Windows - Embedded www.devbuzz.com www.knowdotnet.com http://www.msmvps.com/williamryan/ "Jon Fairchild" <jon.fairchild@miner.com> wrote in message news:595e225.0405201126.38235579@posting.google.com... > "Index was out of range" error when editing DataRow > > Our application makes thousands of edits to DataSets without problem, > but occasionally this error appears: "Index was out of range. Must be > non-negative and less than the size of the collection. Parameter name: > index" > > I have found one place in the code where I can reproduce the error, > though still intermittently. In this case I am changing the value of > field in a DataRow. This field happens to be a foreign key to a parent > table. The parent table contains "Incidents" and the child table > contains "Devices", and they are related through an "Incident ID". > Here is the code that fails occasionally: > > deviceRow["INCIDENT_ID"] = newIncidentID; > > My testing indicates that the column name and value are valid. As the > stack trace of the error shows, the problem instead has to do with > changing the row state during the edit: > > Exception: System.ArgumentOutOfRangeException > Message: Index was out of range. Must be non-negative and less than > the size of the collection. > Parameter name: index > Source: mscorlib > at System.Collections.ArrayList.get_Item(Int32 index) > at System.Data.DataTable.RecordStateChanged(Int32 record1, > DataViewRowState oldState1, DataViewRowState newState1, Int32 record2, > DataViewRowState oldState2, DataViewRowState newState2) > at System.Data.DataTable.SetNewRecord(DataRow row, Int32 > proposedRecord, DataRowAction action, Boolean isInMerge) > at System.Data.DataRow.EndEdit() > at System.Data.DataRow.set_Item(DataColumn column, Object value) > at System.Data.DataRow.set_Item(String columnName, Object value) > > > Any ideas on what could be causing this? > > Thanks, > Jon Fairchild |
|
|
|
#3 |
|
Guest
Posts: n/a
|
Hi Bill,
Thanks for your response! The relevant code is scattered around so it is hard to show you a ‘block' per se. But I have collected some code bits to describe the situation to you. First, we take an Incident row that was selected by the user in a grid. We create a view on the Device table to get the Device children of the selected Incident. //create a device dataview with an explicit filter to ensure it will show //only devices for this incident, taking edits into account _incidentSet = incidentRow.Table.DataSet; DataTable deviceTable = _incidentSet.Tables[RxDb.Tables.IncidentDevices.TableName]; DataView deviceView = new DataView(deviceTable); string rowFilter = string.Format("{0} = {1}", RxDb.Tables.IncidentDevices.IncidentID, incidentID); deviceView.RowFilter = rowFilter; We open a form that displays this list of Devices in a tree. The form contains an ‘edit view' control where the user can edit attributes for the Device currently selected in the tree. An edit view contains multiple sub-controls called ‘field views', each one bound to a column in the table. Here is the binding code from within the field view: //set the current row of the DataTable binding context to this DataRow _currencyManager = this.BindingContext[dataRow.Table] as CurrencyManager; _currencyManager.Position = 0; DataRowView currentView = _currencyManager.Current as DataRowView; DataRow currentRow = currentView.Row; while (!(DataSetConfig.AreSameRows(currentRow, dataRow))) { _currencyManager.Position++; if (_currencyManager.Position > _currencyManager.Count) break; currentView = _currencyManager.Current as DataRowView; currentRow = currentView.Row; } Also we use a currency manager at the form level to track this binding: //get the currency manager for the binding of the DataView in the edit view _currencyManager = deviceEditView.BindingContext[deviceView.Table] as CurrencyManager; We set the view's filter state to show only current rows, as some of the tools on the form will remove Devices from the tree by deleting the Device row. //filter the device view so that only current rows are visible //(non-deleted rows) deviceView.RowStateFilter = DataViewRowState.CurrentRows; One tool on the form is ‘Save as New Incident'. This tool creates a new row in the Incident table, and updates the Devices selected in the tree to be children of the new Incident. The last line below generates the error: //get the existing parent incident DataRow existingIncident = selectedDevices[0].GetParentRow (RxDb.Relations.Incidents_IncidentDevices); DataTable incidentTable = existingIncident.Table; //create a new incident DataRow newIncident = incidentTable.NewRow(); incidentTable.Rows.Add(newIncident); int newIncidentID = Convert.ToInt32(newIncident[RxDb.Tables.Incidents.ID]); foreach(DataRow deviceRow in selectedDevices) { //assign device to the new incident deviceRow[RxDb.Tables.IncidentDevices.IncidentID] = newIncidentID; } If the error does not occur, we then proceed to set some default values on the new Incident row, and show a dialog with its own bound edit view so the user can edit the new incident. One thing to note is that the user can cancel the Incident dialog, thus canceling the ‘Save as new Incident' tool. In this case the selected Devices stay with their current Incident parent and the new Incident is deleted. I reproduce this error best by running and canceling ‘Save as New Incident' a few times. Here is the code that cleans up when the user cancels: //quit now if user cancelled if (result == DialogResult.Cancel) { //set devices back int existingIncidentID = Convert.ToInt32(existingIncident[RxDb.Tables.Incidents.ID]); foreach(DataRow deviceRow in selectedDevices) { deviceRow[RxDb.Tables.IncidentDevices.IncidentID] = existingIncidentID; } //delete new incident that was created newIncident.Delete(); return; } I have try the following tests, but none of them have made the error go away: 1. I commented out the code that sets the DataView's row filter state. 2. I removed the use of a DataView completely and worked with a table only. 3. I commented out all binding and currency manager code. 4. I made the tool reassign Devices to an existing Incident row rather than a new one. 5. I commented out the code that deletes the new Incident row upon cancel. I hope this description of the situation is adequate. Thanks for your help with this issue! -Jon Fairchild "William Ryan eMVP" <dotnetguru@comcast.nospam.net> wrote in message news:<ebBgs6sPEHA.2444@TK2MSFTNGP12.phx.gbl>... > Hi Jon: > > Could you post the code block around it? There could be a few things going > on but changing rowstate happens whenver you edit, I don't think that's the > problem. If it works most of the time, I'm wondering if you aren't calling > .Remove or something like that which could be throwing off your counter loop > or something. I can't really tell from this and although the stack trace is > usually helpful, I can't see much there. > > Let me know and I'll see what I can come up with. > > Cheers, > > Bill > > -- > W.G. Ryan MVP Windows - Embedded > > www.devbuzz.com > www.knowdotnet.com > http://www.msmvps.com/williamryan/ |
|
|
|
#4 |
|
Guest
Posts: n/a
|
We found a patch from Microsoft that fixes this problem for us. See
MSDN Knowledge Base article 836874. http://support.microsoft.com/defaul...kb;en-us;836874 -Jon Fairchild |
|
![]() |
|
| Thread Tools | |
| Rate This Thread | |
|
|

Main Page 

