关于DataTable内部索引已损坏的解决办法

这个问题困扰了我很久,我想很多用.Net2.0的人也有碰到过。错误信息如下:

我用静态DataTable对象记录用户上线下线,一开始没有问题,大概半天以后出现一下错误,也不知道是什么问题,一旦出现这个问题,程序就挂掉了,即使用了try和catch也不行。错误如下:
---------------------------------------------------------------------------------------

DataTable 内部索引已损坏:“5”。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

异常详细信息: System.InvalidOperationException: DataTable 内部索引已损坏:“5”。

源错误:

执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。 

堆栈跟踪:


[InvalidOperationException: DataTable 内部索引已损坏:“5”。]
   System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 position) +431
   System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 position) +846
   System.Data.RBTree`1.Insert(K item) +24
   System.Data.Index.InitRecords(IFilter filter) +1691978
   System.Data.Index..ctor(DataTable table, Int32[] ndexDesc, IndexField[] indexFields, DataViewRowState recordStates, IFilter rowFilter) +175
   System.Data.Select.CreateIndex() +1199
   System.Data.Select.SelectRows() +267
   System.Data.DataTable.Select(String filterExpression) +65
   MsgService.MyServer.checkUserExist(String UserID, String Domain) +167
   MsgService.Migrated_Ref.addUser() +132
   MsgService.Migrated_Ref.Page_Load(Object sender, EventArgs e) +292
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34
   System.Web.UI.Control.OnLoad(EventArgs e) +99
   System.Web.UI.Control.LoadRecursive() +47
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061

 


--------------------------------------------------------------------------------
版本信息: Microsoft .NET Framework 版本:2.0.50727.42; ASP.NET 版本:2.0.50727.42

 
也在CSDN上面发了帖子,但是一直没有解决,后来在MSDN上面寻到了解决方法,放上来让大家给大家参考。

 解决的办法其实很简单,只要了解出错原因。
一般我们会使用DataTable.Select()方法来筛选数据,而DataTable会在执行Select()方法的时候系统会默认创建一个DataView,而DataView创建的时候会创建内部索引,如果这个时候数据被操作(添加,删除),那么内部索引就会被破坏,从而出错。大概是这个意思吧,不知道有没有说错。所以解决的方法也很简单,就是新建一个DataView,并在创建DataView的时候锁定DataTable。
DataView myDV;
lock(myTable)
{
    myDV=new DataView(myTable,"过滤","排序",DataViewRowState.CurrentRows);

    //数据操作
}

原文如下:

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.

 下面是原文地址:http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=277680&SiteID=1&PageID=1

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值