Exception: DataTable internal index is corrupted: '5'. on …-Collection of common programming errors
msdnHi, I have a problem with bindingsource component in framework 2.0.
I have a combobox bound to a bindingsource which is also bound to a dataset with 2 related tables and a datagridview bound to the same bindingsource. What I want to do is : When the selectedindex property of my combobox changes, the corresponding cell value must be changed in the datagridview. But although the value in bindingsource changes, datagridview does not display the new value. That value is displayed after I move the mouse over that cell and make it invalidate its region manually.
Another error I caught is the one that you can see as the subject of my post. I do not know why i have that message when I try to change the property of ((DataRowView)mybindingsource.Current)[“MyProperty”] programmatically.
I will be grateful if someone can help me.
-
132 Answers
msdn1Post a code example for the internal index is corrupted issue, this sounds like a bug.
Sorry I can’t help you on the binding issue.
msdn2Hi Matt,
I have the same problem.
I have a typed dataset and sometimes, I don’t know why, when I want to select some information in a DataTable and show (no Databinding) some information on my webpage I get this error.
Here is the exact exception :
StackTrace : Source: System.DataMethode: RBInsertMessage: DataTable internal index is corrupted: ‘5’.StackTrace : at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 position)at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 position)at System.Data.Index.InitRecords(IFilter filter)at System.Data.Index..ctor(DataTable table, Int32[] ndexDesc, IndexField[] indexFields, DataViewRowState recordStates, IFilter rowFilter)at System.Data.Select.CreateIndex()at System.Data.Select.SelectRows()at System.Data.DataTable.Select(String filterExpression)
at Composants_Publicite.Afficher()
It can work for many days and then I suddenly get this exception.
I can send you some code but I can’t post it here due to security reason.
Thx for your help.
msdn3I’ll check with the devs to see if they’ve heard of this one yet.
msdn4We have a bug filed on this but we have not narrowed down a way to reproduce this yet. Could you reply to me with some information on how you manipulate this DataTable?
For example are you modifying this DataTable from multiple threads concurrently?
It is possible that this could corrupt it. According to the devs:The internal index is corrupted “5” message typically gets thrown when 2 or more rows end with the same row id.
This is a problem for DataTable because the row id should always be unique.
So I theorize if 2 threads simultaneously add rows to the DataTable this could cause the corruption.
msdn5Yes It could be the problem.
My DataSet is stored on the Application Cache and every user can potentialy access and, sometimes, modify the content of a row.
But I had another exception telling that I cannot modify the same row at the same time. Now I modify it in order that the DataSet is now read only and I have no more exception on this DataSet.
msdn6after I red this thread I’m sure it is a bug in .NET framwork 2.0. I discoverd this exception several times in different applications. but yet I was unable to reproduce it while debugging 🙁
.. and it could not be a threading problem, having two thread inserting data, because I do not user different threads on that DataSet.
any news on it from MS ?
msdn7We’re still looking for a repro. So if anyone out there has a repro please post it here.
Also if you have some code that reproduces it but not consistently post this too.
Anything that could help us figure out how to reproduce would be good, thanks for all your help thus far folks!
msdn8Note someone forwarded one repro to me thus far and it turns out that this one was caused by multi-threaded access to the DataTable.
So key thing for everyone to note. If you modify a DataTable on multiple threads, you can corrupt the indexes on it and this is by design. The DataTable is not designed to be thread safe for modifications for performance reasons. So to resolve this you need to use the lock statement around all modifications to DataTable.
Modifications include:
1. Adding, deleting, modifying rows in DataTable.
2. Selecting rows using Select method on DataTable (yes, this can modify the DataTable by creating a new index on it).
3. Creating DataViews over a DataTable (same as #2, this can cause a new index to be created on DataTable).
4. Modifying Sort property.
I am sure there are some others I missed. In general using the same DataTable on multiple threads is tricky business unless you restrict DataTable to100% read only operations (like enumerating rows and reading values).
msdn9I am 100% sure, that this bug has nothing to do with multiple-thread. Our users ran into the bug several times a day. Now I implemented the following work-around:
‘ ————————————————————————————————
dt.Clear()Me.Owner.DbConnector.FillDataAdapter(da, dt)
.SuspendBinding()
Table.BeginLoadData()
Table.DataSet.Merge(dt, False, MissingSchemaAction.Add)
Table.EndLoadData()
.ResumeBinding()
‘ ————————————————————————————————
I added the red-maked-code to the method where I do the .Reload of my DataSet. (The same Code is used after saving the Table.)
On the side of the user-code I do not change anything. Just using NewRow and Rows.Add. – what caused the corrupted: ‘5’ Error before. And now the error is gone.
‘ ————————————————————————————————
Dim
NewRow As DataRow = Me.Table.NewRow
…
Me
.Table.Rows.Add(NewRow)
msdn10I am getting this same “data table internal index is corrupt ‘5’” error when trying to update a row using one of the table adapters I created with a data source in VS 2005. This code has been working without problems for months. The error occurs about 30% of the time. Here is an example of the code I am using:
DataRowView rv = (DataRowView)myBindinfSource.Current;
myDataSource.myTableDataRow row = (myDataSource.myTableDataRow)rv.Row;
row.ID = 12;
int updated = mtTableTableAdapter.Update(row);
myDataSource.AcceptChanges();
Does anyone at least know of any work arounds?
msdn11
msdn12I have tried using the Begin/EndLoadData as well as the Suspend/ResumeBinding tricks to try to get this to work but this error keeps rearing its’ ugly head…still only sometimes though. I really wish I could find more information regarding why this could be happening. I am not using threads at all…..
msdn13I seem to be able to reproduce this fairly consistently. I’m handling the CurrentItemChanged event on the binding source and using that to detect changes to one column that need to be propogated to others. Whenever I set a value against a column using the binding source Current property to access the DataRowView I get this exception.
I’ve tried all the work arounds, but none seem to work. It doesn’t seem to matter which event I connect to from the binding source, they all seem to throw this exception if I try to change the underlying data.
msdn14Could you post a repro so I can get this to the dev who owns the bug?
Thanks!
msdn15To reproduce it :
1) Load a datatable with a dataadapter
2) modify a data and save it to the database “without” closing the form and then modify the data again and save to the database again
3) That’s all
msdn16We found a consistent way to reproduce this:
using Asp.Net:
– use a DataTable and store it in the cache
– Create a DataView on the table
– Bind a control to the DataView (this step is not necessary I think)
– stress test the web page, sending multiple http requests at the same time.
Very soon the error will start to appear.
msdn17Yes, this goes back to my original theory.
A DataTable is thread safe for read operations but not for write operations.
So this means you can store a DataTable in the cache and extract it and use it in a read only fashion and it will work fine.
However, creating a DataView on a DataTable is a write operation on a DataTable. Most people don’t know this, and its not very intuitive so I don’t blame them for not knowing this.
What happens when you create a DataView on a DataTable is the DataView will create an index on the DataTable and this index is stored in the DataTable. The reason for this is performance, for example if you create a DataView saying “F1=1” as the criteria, this creates an internal index on the DataTable to locate this information. Later on if you create another DataView with the same criteria, the index is reused, so this improves performance. However the fact that these indexes are stored inside the DataTable means that these are write operations to the DataTable and thus they are not thread safe.
So if you are creating random DataViews on the DataTable you are constantly creating new indexes. If you are creating the same type of DataView over and over you are constantly reusing existing index.
So unfortunately you need to serialize the creating of DataViews over the DataTable.
You could do this for example to avoid the problem:
lock(myDataTableFromCache)
{
dv = new DataView(myDataTableFromCache,…);
}
So lock using the DataTable as the locking object and lock when creating the DataView should solve the problem.
msdn18OK, I met this error as well but in bit different circumstances…
I have 2 tables in my dataset (loaded from xml file).
I have 2 DataGridViews which are bound to 2 BindingSources respectively.
my user need to be able to move a line from DataGridView A to DataGridView B and back.
In my code I create new row of Table B, fills it with values from line aa of DataGridView A, add the row to table B and delete the line aa from DataGridView A.
When moving line from DataGridView B to DataGridView A I do the same just the in opposite direction.
I get the error after doing several move like described on the same line.
A->B, B->A, A->B and get the error on this line:
Me.Ds.dtB.Rows.Add(NewRow)
and the weirdest thing is that when I surround the code with “try catch” – I saw the error in a messagebox but the line did enter Table B and DataGridView B !!!!!!!!!!
When tried to move it back to DataGridView A – I got the same error again but this time an empty row has been added to table A and DataGridView A.
Hope this help a little and that a solution is on the way…
msdn19Sorry to burst your bubble on this, but I have a reproduction scenario on this which does not have anything to do with threading. It seems to have to do with expression field updating using the CHILD() expression function.
I will post a code sample as soon as I can isolate one.
Andy
Another Item – if I use the lock statement to lock the row I’m operating on, then the code works fine. Are expression evaluations performed out of band on a different thread???
msdn20Awesome, if you can get me the repro code I can give it straight to the dev that wrote the DataSet and we can get this fixed.
msdn21To correct my prior statements, the lock keyword did NOT work reliability. However, as this is a sometimes works/sometimes doesn’t problem, I would suspect a race condition.
msdn22Note as a follow up I talked to the DataSet gurus and they indicated that with .NET 2.0 creating DataView is now protected by internal locks so in theory there is no need to syncrhonized creating DataViews over a DataSet with .NET 2.0.
Still looking for a repro for this one. I put together some test code on my own to stress multi-threaded DataView creation and could not reproduce any failures.
msdn23Any ideas on a similar error (’13’ instead of ‘5’):
System.InvalidOperationException: DataTable internal index is corrupted: ’13’. at System.Data.RBTree`1.GetNodeByIndex(Int32 userIndex) at System.Data.Index.GetRows(Range range) at System.Data.Index.GetRows(Object[] values) at System.Data.DataRelation.GetChildRows(DataKey parentKey, DataKey childKey, DataRow parentRow, DataRowVersion version) at System.Data.DataRow.GetChildRows(DataRelation relation, DataRowVersion version) at System.Data.DataRow.GetChildRows(DataRelation relation) at Store24.Store24Lib.ScrubProductsTable(DataRelation relation, String exclCategories, String[] productExcludeArray) in C:\Documents and Settings\chrwil\My Documents\Visual Studio 2005\Projects\Store24.2\Store24.2\Store24.cs:line 1956
private static void ScrubProductsTable(DataRelation relation, string exclCategories, string[] productExcludeArray) { foreach (DataRow parentDataRow in relation.ParentTable.Rows) { bool allProdsDeleted = ScrubProductsTable(parentDataRow.GetChildRows(relation), exclCategories, productExcludeArray); if (allProdsDeleted) { parentDataRow.Delete(); // No children so kill parent } } } private static bool ScrubProductsTable(DataRow[] dataRows, string exclCategories, string[] productExcludeArray) { bool allProdsDeleted = true; // Return value At least 1 row remains foreach (DataRow mDataRow in dataRows) { if (exclCategories.Contains((string)mDataRow["sales_category_id"]) || Array.BinarySearch(productExcludeArray, mDataRow["product_id"]) >= 0) { mDataRow.Delete(); } else { allProdsDeleted = false; // At least 1 child row remains so do not delete parent } } return (allProdsDeleted); }
msdn24I think the problem was that the DataTable was in a DataSet that was in cache. Perhaps another user was doing the same thing with the same DataSet at the same time. I need to make a copy of the object before deleting rows from it.
GarDavis
msdn25Yes this is very possible. I know a few years ago I was working with a customer who was using DataSet as a cache of data and one thing we did to avoid issues was implement a “copy on write” scheme. So you setup some code where if the caller wants to modify the DataSet they call a special function to get a copy and then modify the copy and when the modification is finished the writer copies over the older copy.
The writer “checks out” a copy, modifies the copy, then “checks in” the new copy.
Readers always get a static copy since the assignment of a DataSet to a variable is atomic. The only special case scenario you had to watch out for was multiple concurrent writers (we just used a global lock to handle this because writes were relatively rare).
msdn26We found that we received this exception due to side effects of BindingManagerBase.EndCurrentEdit that caused a second nested call to EndCurrentEdit OR SuspendBinding. This was due to the way we save our data to the database in our UI and we were able to code around it. The exception never occured in 1.1 of the framework however.
msdn27 Any news about this issue?I’ve got the same problem with a multithreaded application. Unfortunately locking is no option because the app is performance critical. In my humble opinion it’s a shame that such an essential data type is not working properly for months. This situation is typical for MS, this bug is apparent for months and nothing satisfying happened. You folk’s should release the source code, surely somebody would fix this problem for you before you do.
msdn28I discoverd that this bug only appears if the Defaultview.Sort property has been set and a Column-Value wich belongs to .Sort will be changed. The Exception occured every 10-20 Row-Changes to a Col (included in .Sort).
After I eleminated the Sort (now I load the records from SQL Server in order), the exception does not appear any more.
Maybe this helps you to find the bug. more info needed, please dont hesitate contacting me.
‘ — Code Segment ————–
Private Sub FlexGrid_CellChanged(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.RowColEventArgs)
Dim
Row As DataRow = Me.FindDataRow(e.Row)
Dim ColName As String = Me.FlexGrid.Cols(e.Col).ColumnName
Try
If IsNothing(Me.FlexGrid(e.Row, e.Col)) Then
Row(
ColName) = System.Convert.DBNullElse
Row(
ColName) = Me.FlexGrid(e.Row, e.Col)