DataTable内部索引已损坏 [英] DataTable internal index is corrupted

查看:2408
本文介绍了DataTable内部索引已损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用C#中的.NET WinForms应用程序,针对3.5 .NET框架运行。在这个应用程序中,我正在将 DataColumn 中的.Expression成员设置在 DataTable 中,如下所示:

  DataColumn column = dtData.Columns [TestColumn]; 
column.Expression =some expression;

第二行,我实际设置表达式,有时会导致以下异常:

  FileName = 
LineNumber = 0
Source = System .Data
TargetSite = Int32 RBInsert(Int32,Int32,Int32,Int32,Boolean)
System.InvalidOperationException:DataTable内部索引已损坏:'5'。
在System.Data.RBTree`1.RBInsert(Int32 root_id,Int32 x_id,Int32 mainTreeNodeID,Int32位置,Boolean append)
在System.Data.RBTree`1.RBInsert(Int32 root_id,Int32 x_id ,Int32 mainTreeNodeID,Int32 position,Boolean append)
在System.Data.Index.InitRecords(IFilter过滤器)
在System.Data.Index.Reset()
在System.Data.DataTable .ResetInternalIndexes(DataColumn列)
在System.Data.DataTable.EvaluateExpressions(DataColumn列)
在System.Data.DataColumn.set_Expression(字符串值)

在错误发生时,没有可察觉的押韵或理由;在加载相同的数据集时,它可能会正常工作,但是重新加载会失败,反之亦然。这导致我认为它与竞争条件有关,在我尝试修改其中一个列时,在 DataTable 上发生另一个写入操作。但是,与 DataTable 相关的代码不是多线程,只能在UI线程上运行。



我已经在网上搜索过,并且 Microsoft论坛,并且在这个问题上有很多讨论和混乱。回到2006年第一次这个问题的时候,想到这是.NET框架的一个缺陷,而且有一些假定的修补程序被推出后来的.NET框架版本。然而,人们报告了应用这些修补程序的混合结果,这些修补程序不再适用于当前框架。



另一个普遍的理论是DataTable上有操作,虽然似乎无害,实际上是写作操作。例如,基于 DataTable 创建新的 DataView 实际上是对表本身的一个写操作,因为它创建 DataTable 中的内部索引,供以后参考。这些写操作不是线程安全的,所以有时会发生竞争条件导致我们访问 DataTable 的非安全写入。这反过来又导致 DataTable 的内部索引损坏,从而导致异常。



我已经尝试在每个 DataView 之间放置在代码中创建,但是,正如我之前提到的,使用 DataTable 的代码没有线程,而锁定没有任何效果,在任何情况下。



有没有人看到这个并成功地解决/解决了它?






不,不幸的是我不能。加载DataTable已经发生在我拿到它以将表达式应用于其DataColumn之一之前。我可以删除列,然后使用您建议的代码重新添加它,但是有什么特别的原因为什么会解决内部索引是损坏的问题?

解决方案

在导入行时,我刚刚遇到了同样的问题,似乎在插入之前调用 DataTable.BeginLoadData p>

编辑:事实证明,这只是固定在一边,现在添加行会抛出这个异常。



Edit2:根据罗伯特·罗斯尼也修复了我的添加问题。我简单地从 DataGridView 中删除​​ DataSource ,并在完成 DataTable



编辑3:仍然没有修复...异常在我的代码的所有不同的地方不断爬行自从星期四以来,这是迄今为止我在框架中遇到的最奇怪和最糟糕的错误(我已经看到许多奇怪的事情在3年来一直在使用.NET 2.0,足以保证我未来的一个项目不会被建立在其上)。但是足够的咆哮,回到主题。



我已经阅读了整个讨论在Microsoft支持论坛,我会给你一个简要的总结。原始的错误报告始于'05




  • 06年3月: 调查开始。在明年的整个过程中,有不同的形式和不同的表现。

  • 3月'07: 最后数字KB 932491的修补程序被发布(不要让你的希望),它链接到一个完全不相关的寻找修补程序的下载,或者至少这样看来。在接下来的几个月中,许多人都报告说,修补程序不起作用,有些报告成功。

  • July '07: 来自微软的最后一个迹象(完全无用的答案),除此之外,微软没有进一步的回应。没有进一步的确认,没有尝试的支持,没有要求更多的信息.​​..没有。除此之外,只有社区相关信息。



没有认真的,这在我看来总结。我可以从整个讨论中提取以下信息:




  • DataTable 线程安全。如果您在任何地方使用多线程,您将不得不将锁定 / 自己同步 li>
  • 索引的损坏发生在之前的之前,实际的异常被抛出。

  • 一个可能的损坏来源是应用的表达式或应用的 Sort

  • 另一个可能的来源是 DataTable.ListChanged()事件,永远不要修改此事件中的数据或从中生成的任何事件。这包括不同的更改的事件从绑定的控件。

  • 绑定 DefaultView 对照。始终使用 DataTable.BeginLoadData() DataTable.EndLoadData()

  • 创建和操纵 DefaultView DataTable (及其中的写入操作飞行意大利面条怪物知道为什么索引



这很可能是在我们的源代码或框架的代码中的竞争条件。看来,微软无法修复这个错误或者无意。无论哪种方式,请检查您的代码是否符合竞争条件,这与我认为的 DefaultView 有关。在某些时候,一个插入或操纵数据会破坏内部索引,因为更改没有通过整个 DataTable



当我找到更多的信息或其他修复时,我当然会报告。对不起,如果我在这里感到有点情绪化,但是我花了三天的时间试图找出这个问题,慢慢开始看起来像是一个很好的理由来获得新的工作。



Edit4:我可以通过完全删除绑定( control.DataSource = null; )来避免此错误,在数据加载完成后添加。这使我认为它与 DefaultView 以及从绑定控件产生的事件有关。


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 DataTable, like so:

DataColumn column = dtData.Columns["TestColumn"];
column.Expression = "some expression";

The 2nd line, where I actually set Expression, will sometimes result in the following exception:

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)

There is no perceptible rhyme or reason as to when the error will occur; in loading the same data set, it may work fine but then reloading it will fail, and vice versa. This leads me to think it is related to a race condition, where another write operation is occurring on the DataTable as I'm trying to modify one of its columns. However, the code relating to DataTables is not multi-threaded and runs only on the UI thread.

I have searched the web and Microsoft forums, and there is much discussion and confusion over this issue. Back when the issue was first reported in 2006, the thought was that it was an flaw in the .NET framework, and there were some supposed hotfixes released that were presumably rolled into later versions of the .NET framework. However, people have reported mixed results in applying those hotfixes, which are no longer applicable to the current framework.

Another prevailing theory is that there are operations on the DataTable which, though seemingly innocuous, are actually write operations. For example, creating a new DataView based on a DataTable is actually a write operation on the table itself, because it creates an internal index in the DataTable for later reference. These write operations are not thread-safe, so it sometimes happens that a race condition leads to an unthread-safe write coinciding with our access of the DataTable. This, in turn, causes the internal index of the DataTable to become corrupted, leading to the exception.

I have tried putting lock blocks around each DataView creation in the code, but, as I mentioned before, code utilizing the DataTable is not threaded, and the locks had no effect, in any case.

Has anyone seen this and successfully solved / worked around it?


No, unfortunately I can not. Loading the DataTable has already occurred by the time I get a hold of it to apply an Expression to one of its DataColumn's. I could remove the column and then re-add it using the code you suggested, but is there a particular reason why that would solve the internal index is corrupted problem?

解决方案

I just had the same issue while importing rows, as it seems, calling DataTable.BeginLoadData before the insert fixed it for me.

Edit: As it turns out, this only fixed it on one side, now adding rows throws this exception.

Edit2: Suspending binding as suggested by Robert Rossney fixed the adding problem for me, too. I simply removed the DataSource from the DataGridView and readded it after I was done with the DataTable.

Edit3: Still not fixed...the exception keeps creeping up in all different places in my code since Thursday...this is by far the strangest and most f****ing bug I've encountered in the Framework so far (and I've seen many odd things in the 3 years I've been working with .NET 2.0, enough to warrant that not a single of my future projects will be build on it). But enough of ranting, back on topic.

I've read through the whole discussion at the Microsoft support forums and I'll give you a brief summary of it. The original bug report originates in '05.

  • March '06: Bug is reported the first time, investigation starts. Throughout the course of the next year it is reported in different forms and different manifestations.
  • March '07: Finally a hotfix with number KB 932491 is released (don't get your hopes up), it links against a download of an completely irrelevant looking hotfix, or at least so it seems. Throughout the next months many report that the hotfix does not work, some are reporting success.
  • July '07: Last sign of live from Microsoft (with a complete useless answer), beyond this point is no further response from Microsoft. No further confirmations, no attempts on support, no requests for more information...nothing. Beyond this point there's only community related information.

No seriously, this sums it up in my opinion. I was able to extract the following information from the whole discussion:

  • The DataTable is not Thread-Safe. You'll have to Lock/Synchronize it on your own if you have Multi-Threading anywhere on it.
  • The corruption of the index happens somewhere before the actual exception is thrown.
  • One possible corruption source is either an applied Expression or an applied Sort.
  • Another possible source is the DataTable.ListChanged() event, do never modify data in this event or any event which spawns from it. This includes different Changed events from bound controls.
  • There are possible issues when binding the DefaultView against a control. Always use DataTable.BeginLoadData() and DataTable.EndLoadData().
  • Creation and manipulation of the DefaultView is a writing operation on the DataTable (and its Index), the Flying Spaghetti Monster knows why.

The possible source of this is most likely a race condition, either in our source code or in the code of the framework. As it seems, Microsoft is unable to fix this bug or has no intention to. Either way, check your code for race conditions, it has something to do with the DefaultView in my opinion. At some point an Insert or a manipulation of the data is corrupting the internal Index because the changes are not properly propagated through the whole DataTable.

I'll of course report back when I find further informations or additional fixes. And sorry if I get a little bit emotional here, but I've spent three days trying to pinpoint this issue, and it slowly starts to look like a good reason to get a new job.

Edit4: I was able to avoid this bug by completely removing the binding (control.DataSource = null;) and re-adding it after the loading of the data is completed. Which fuels my thought that it has something to do with the DefaultView and the events which spawn from the bound controls.

这篇关于DataTable内部索引已损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆