I am working with a .NET WinForms app in C#, running against the 3.5 .NET framework. In this app, I am setting the .Expression member of a DataColumn
in a
can't you just use:
dtData.Columns.Add("TestColumn", typeof(Decimal), "Price * Quantity");
You mention "not threadsafe". Are you manipulating the object from different threads? If so then that might very well be the reason for the corruption.
This is how I fixed my Internal index is corrupted problem:
System.Data.DataTable dtNew = new DataTable();
for (int iCol = 0; iCol < dtOriginalData.Columns.Count; iCol++)
{
dtNew.Columns.Add(dtOriginalData.Columns[iCol].ColumnName, dtOriginalData.Columns[iCol].DataType);
}
for (int iCopyIndex = 0; iCopyIndex < item.Data.Rows.Count; iCopyIndex++)
{
dtNew.Rows.Add(dtOriginalData.Rows[iCopyIndex].ItemArray);
//dtNew.ImportRow(dtOriginalData.Rows[iCopyIndex]);
}
dtOriginalData = dtNew;
Enjoy, Andrew M
Had the same with .NET 4.5.2 win forms app. In my case the reason appeared to be multiple controls bound to single BindingSource column. I am aware that binding many controls to one value is asking for trouble but I it has been the lesser evil for me due to pretty complex layout.
It appeared that changing the value from one side raised multiple OnChange events trying to perform the same operation against the BindingSource which resulted with the error in question.
I have tried suspending binding but with no success. I have implemented flags preventing the code from being executed many times on parallel and things are better.
In my case the Framework version is 2.0. The source of a problem was in DataView ListChanged event. The code below initializes the new row with some default values.
private void dataView_ListChanged(object sender, ListChangedEventArgs e)
{
if (e.ListChangedType == ListChangedType.ItemAdded)
{
DataView v = (DataView)sender;
DataRowView drv = v[e.NewIndex];
// This "if" works fine
if (drv["Foo"] == DBNull.Value)
{
drv["Foo"] = GetFooDefault();
}
// This "if" brakes the internal index
if (drv["Bar"] == DBNull.Value && drv["Buz"] != DBNull.Value)
{
drv["Bar"] = drv["Buz"];
}
}
}
After some investigation it became clear that ItemAdded event is called at least twice per row. First time when the UI creates new line for entering data and second time, well I'm not sure, but looks like when the DataRowView is added to a DataView.
The first "if" works only when the ItemAdded is called first time. On second call "Foo" column is already populated and left as is.
However the "Bar" column defaulting code can be executed on both calls. Actually in my case it was executed only on second ItemAdded event, when the user had a chance to fill in the data for "Buz" column (initially "Buz" has DBNull value).
So here is recommendations based on my findings:
e.ListChangedType == ListChangedType.ItemAdded
.DBNull.Value
etc.)Personally, this particular bug has been my nemesis for 3 weeks in various fashions. I have solved it in one part of my code base and it shows up elsewhere (I believe I finally squashed it tonight). The exception info is rather unhelpful, and a way to force a reindex would have been a nice feature given the lack of MS to solve the problem.
I wouldn't look for MS's hotfix -- they have a KB article on it, then redirect you to an ASP.Net fix that is completely unrelated.
Ok - enough complaining. Let's see what has actually helped me in resolving this particular issue in the various places I've encountered it:
This has probably helped me the most (absurd as it sounds): If a value is not changing, don't assign it. So in your case use this instead of your outright assignment:
if (column.Expression != "some expression") column.Expression = "some expression";
(I removed the square brackets, not sure why they were there).
Edit (5/16/12): Just ran into this issue repeatedly (with an UltraGrid/UltraWinGrid). Used the advice of removing the sort on the DataView, and then added a sorted column which matched the DataView sort, and this resolved the issue.