Я работаю с приложением .NET WinForms в C #, работающем на платформе 3.5 .NET. В этом приложении я устанавливаю член .Expression для DataColumn
в DataTable
, например:
DataColumn column = dtData.Columns["TestColumn"];
column.Expression = "some expression";
Вторая строка, где я на самом деле установил Expression
, иногда приводит к следующему исключению:
FileName=
LineNumber=0
Source=System.Data
TargetSite=Int32 RBInsert(Int32, Int32, Int32, Int32, Boolean)
System.InvalidOperationException: DataTable internal index is corrupted: '5'.
at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
at System.Data.Index.InitRecords(IFilter filter)
at System.Data.Index.Reset()
at System.Data.DataTable.ResetInternalIndexes(DataColumn column)
at System.Data.DataTable.EvaluateExpressions(DataColumn column)
at System.Data.DataColumn.set_Expression(String value)
Нет заметной рифмы или причины того, когда произойдет ошибка; при загрузке одного и того же набора данных он может работать нормально, но затем перезагрузить его не удастся, и наоборот. Это заставляет меня думать, что это связано с состоянием гонки, когда на DataTable
происходит другая операция записи, когда я пытаюсь изменить один из его столбцов. Однако код, относящийся к DataTable
s, является , а не многопоточным и выполняется только в потоке пользовательского интерфейса.
Я искал в Интернете и форумах Microsoft , и по этому вопросу много дискуссий и путаницы. Когда в 2006 году впервые сообщили об этой проблеме, предполагалось, что она является недостатком .NET Framework, и было выпущено несколько предполагаемых исправлений, которые предположительно были добавлены в более поздние версии .NET Framework. Тем не менее, люди сообщают о неоднозначных результатах применения этих исправлений, которые больше не применимы к текущей структуре.
Другая распространенная теория заключается в том, что в DataTable существуют операции, которые, хотя и кажутся безобидными, на самом деле являются операциями записи. Например, создание нового DataView
на основе DataTable
на самом деле является операцией записи в самой таблице, поскольку оно создает внутренний индекс в DataTable
для дальнейшего использования. Эти операции записи не являются поточно-ориентированными, поэтому иногда случается, что условие гонки приводит к небезопасной записи, совпадающей с нашим доступом к DataTable
. Это, в свою очередь, приводит к повреждению внутреннего индекса DataTable
, что приводит к исключению.
Я пытался поместить lock
блоков вокруг каждого DataView
создания в коде, но, как я упоминал ранее, код, использующий DataTable
, не является многопоточным, и lock
s не оказали никакого влияния ни на что. случай.
Кто-нибудь видел это и успешно решил / обошел?
Нет, к сожалению, я не могу. Загрузка DataTable уже произошла к тому времени, когда я получил его, чтобы применить Expression к одному из его DataColumn. Я мог бы удалить столбец, а затем снова добавить его, используя предложенный вами код, но есть ли конкретная причина, по которой это могло бы решить проблему повреждения внутреннего индекса?