【问题标题】:Why am I getting this exception为什么我会收到此异常
【发布时间】:2013-11-08 19:32:39
【问题描述】:

我有一个 System.Data.DataSet 和 1 个单表。该表有很多列。

在某个事件处理程序中,我正在为已经存在的数据行中的一个字段设置十进制值(在设置时)。

在极少数情况下,我会收到 ArgumentOutOfRangeException 异常。

消息:System.ArgumentOutOfRangeException:索引超出范围。必须为非负数且小于集合的大小。

调用堆栈:

   at System.ThrowHelper.ThrowArgumentOutOfRangeException()
   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at System.Data.RecordManager.NewRecordBase()
   at System.Data.DataTable.NewRecord(Int32 sourceRecord)
   at System.Data.DataRow.BeginEditInternal()
   at System.Data.DataRow.set_Item(DataColumn column, Object value)
   at CPITS.Data.OrdersRow.set_ExecutionPrice(Decimal value)

奇怪的是,这是在框架生成的代码中发生的(当然,我没有为 DataColumn 编写 Setter)。

你能帮我理解和解决这个问题吗?

编辑

下面是我设置值的代码:

void ibclient_OrderStatus(object sender, OrderStatusEventArgs e)
{
    Data.OrdersRow drOrders = data.Orders.FindByOrderId(e.OrderId);

    if (drOrders != null)
    {
        drOrders.FilledQuantity = e.Filled;
        drOrders.ExecutionPrice = e.AverageFillPrice; //Sporadic Exception when setting a decimal value
    }
}

【问题讨论】:

  • 你能展示你在抛出异常时用来调用它的代码吗?很明显,有些东西试图索引集合中不存在的元素。在没有看到代码或不知道运行时值的情况下,我无法比这更具体。
  • 对不起。添加了相关代码..
  • 我没有看到代码和异常之间的联系。在哪一行代码中抛出了异常?发生这种情况时的运行时值是多少?
  • 代码和异常的联系可以在调用栈的最后一行看到。代码试图在 if 块的第二行中设置一个十进制值,这就是“必须”发生异常的地方。 ('必须',因为这发生在生产环境中;)
  • 请检查 e.AvaerageFillPrice 是否与 ExecutionPrice 数据类型相同,是否在该数据类型范围内。

标签: c# c#-4.0 dataset indexoutofboundsexception


【解决方案1】:

检查您在表格中允许的小数位数,并检查您提交的数字有多少位小数。

如果小数位数超出范围,则会引发此异常。

【讨论】:

  • 我对此表示怀疑!,原因如下。 1.我没有在表中指定任何限制,2.这段代码执行了很多次。
  • 您必须在表中指定限制,这是SQL的语法(例如,您的类型可以是decimal(18,2))。如果您不指定此项,将使用默认值。看看这个有类似问题的链接:stackoverflow.com/questions/12184539/….
【解决方案2】:

DataTable.GetErrors Method

获取包含错误的 DataRow 对象数组。

【讨论】:

    【解决方案3】:

    这是RecordManager.NewRecordBase的反编译代码

    internal int NewRecordBase()
    {
      int num;
      if (this.freeRecordList.Count != 0)
      {
        num = this.freeRecordList[this.freeRecordList.Count - 1];
        this.freeRecordList.RemoveAt(this.freeRecordList.Count - 1);
      }
      else
      {
        if (this.lastFreeRecord >= this.recordCapacity)
          this.GrowRecordCapacity();
        num = this.lastFreeRecord;
        ++this.lastFreeRecord;
      }
      return num;
    }
    

    如您所见,唯一可能出现“索引超出范围”异常的情况是:

    num = this.freeRecordList[this.freeRecordList.Count - 1];
    

    由于 DataTable 不是线程安全的,我们可以很容易地想象这样一种情况:在访问 freeRecordList[..] 之前但在访问 this.freeRecordList.Count 之后,另一个线程删除了一条记录。

    在这种情况下,freeRecordList.Count 会同时发生变化 => index out of bounds 异常。

    因此,如果我是你,我会尝试找出并发问题(它在极少数情况下发生的事实是另一个论点!)

    【讨论】:

    • 这是一个 MS 内部集合,在 drOrders.ExecutionPrice setter 上进行了修改。我给出的代码是 System.Data.RecordManager.NewRecordBase() 的 反编译 代码,它在您的堆栈跟踪中。这不是一个例子。它是实际运行但失败的代码。
    • 您的论点对于您给出的示例是正确的,但该示例并未说明我的情况。我没有任何明确的 COLLECTION(例如您的 freeRecordList),我正在检查其计数并尝试访问它。我所拥有的只是一个 DataSet -> DataTable ->(隐式)dataRows 集合。我正在 查询 一行,然后,如果该行存在,我将更新该行的一列。更新时(即发生异常时),我没有处理任何集合。
    • @Viv :我可以向你保证,你不会有任何其他答案。代码不会说谎,我是对的:/
    猜你喜欢
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多