4

I have a System.Data.DataSet and 1 single table in it. The table has many columns.

Screenshot of the DataSet Designer

In a certain event handler, I am setting a decimal value for one of the fields, in a data row which is already existing (at the time of setting).

In a very rare case, I am getting a ArgumentOutOfRangeException exception.

Message: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.

Call Stack:

   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)

Strange thing is, this is happening from the code which the framework has generated (Of course, I didn't write the Setter for the DataColumn).

Can you please help me understand & fix this problem?

EDIT

Below is the code where I am setting value:

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
    }
}
ViV
  • 1,998
  • 8
  • 27
  • 54
  • 1
    Can you show the code you use to call this when the exception is thrown? Clearly something is trying to index an element that doesn't exist in a collection. Without seeing the code or knowing the runtime values, I can't be more specific than that. – David Oct 29 '13 at 14:59
  • Sorry. Added relevant code.. – ViV Oct 29 '13 at 15:05
  • I don't see the connection between the code and the exception. On what line of code is the exception thrown? What are the runtime values when this happens? – David Oct 29 '13 at 15:08
  • The connection between the code and exception can be seen in the last line of the call stack. Code is trying to set a decimal value in the second line within the if block, and that is where the exception 'must have' occurred. ('Must have' because this has happened in production environment;) – ViV Oct 29 '13 at 15:26
  • Please check whether e.AvaerageFillPrice is of same datatype of ExecutionPrice and also within the range of that datatype. – Sudhakar Tillapudi Nov 06 '13 at 03:48
  • Hi @Sudhakar. they are of same types. That same line gets executed like a thousand times in the timeline of the program. But, randomly it gave this error once. – ViV Nov 06 '13 at 14:24

3 Answers3

3

Here is de decompiled code of 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;
}

as you can see, the only case where you could have a "index out of bounds" exception is here:

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

since there DataTable is not thread safe, we could easily imagine a scenario where a record is removed by another thread before accessing the freeRecordList[..] but after having accessed to this.freeRecordList.Count.

In this case, freeRecordList.Count would have changed in the meanwhile => index out of bounds exception.

Thus, if I were you, I would try to find a concurrency issue (the fact that it happens in rare cases is another argument !)

Olivier
  • 5,578
  • 2
  • 31
  • 46
  • This is a MS internal collection, which is modified on drOrders.ExecutionPrice setter. The code I gave is the ***decompiled*** code of System.Data.RecordManager.NewRecordBase(), which is in your stacktrace. It's not an example. Its the code which actually run and fails. – Olivier Nov 08 '13 at 17:04
  • Your argument is correct for the example you have given, but the example does not illustrate my case. I don't have any sort of an explicit COLLECTION (like your `freeRecordList`), whose Count I am checking, and trying to access it. All that I have is a DataSet -> DataTable -> (implicit) collection of dataRows. I am **Querying** for a row and then, if the row exists, I am updating a column for that row. While updating (that is when the Exception happened), there is no collection I am dealing with. – ViV Nov 08 '13 at 17:04
  • @Viv : I can assure you you wont have any other answer. Code dont lie, I'm right :/ – Olivier Nov 12 '13 at 09:06
2

Check the number of decimal places you are allowing in your table and check how many decimals the number you are committing has.

This exception can be thrown if the number of decimals is out of range.

Igor Ševo
  • 5,459
  • 3
  • 35
  • 80
  • I doubt this!, for the following reasons. 1. I have not specified any limit in table, 2. This piece of code is executed MANY times. – ViV Nov 12 '13 at 14:52
  • 1
    You must specify the limit in the table, that's the syntax of SQL (for example, your type could be `decimal(18,2)`). If you do not specify this, the defaults will be used. Check out this link with a similar problem: http://stackoverflow.com/questions/12184539/mysql-out-of-range-value-for-decimal-column. – Igor Ševo Nov 12 '13 at 16:39
1

DataTable.GetErrors Method

Gets an array of DataRow objects that contain errors.

Imad Alazani
  • 6,688
  • 7
  • 36
  • 58