3

Is it safe to calculate a field value inside an update cursor and refer back to this calculated value to change another field value of the same row?

I think some code will actually explain my question:

ICursor _updateCursor = selectedTable.Update(myQueryFilter, false);
IRow row = _updateCursor.NextRow();
while (row != null) {
            row.set_Value(fieldColumn, (double)row.get_Value(fieldColumn) * 2);
            row.set_Value(fieldColumn+1, (double)row.get_Value(fieldColumn) * 2);
            updateCursor.UpdateRow(row);
            row = _updateCursor.NextRow();
}

The effect I'm looking for is the column at position fieldColumn will have its values doubled and the column next to it will have the original value quadrupled. But is this safe to do? Will I always get the doubled value in my second expression or is there a chance the value will not be written until i flush the cursor object, thus will end up having just the doubled values in the adjacent column?

I did some tests on a really small table (10 rows) and it works the way I want but I have to ensure this will work in tables of tens of thousands of rows

  • 2
    My arcobjects is incredibly rusty and I can't comment as to whether it's safe or not, but to be on the safe side why not store that calculated value in a variable to use in your two fields? – Midavalo Apr 7 '16 at 18:22
  • Actually that's a good idea :) It probably isn't any slower and I'm on the safe side - so, yeah, thank you! – kitty Apr 7 '16 at 19:18
1

Yes, it's safe, until you store the row. The values are changed in the IRow object held in memory immediately but if you call the row separately using ITable.GetRow this is a different (but same) row as it's a different object in separate memory space so its values will not change.

The example you've given is indeed safe because it's working on the same memory object, but you shouldn't do this:

ICursor _updateCursor = selectedTable.Update(myQueryFilter, false);
IRow row = _updateCursor.NextRow();
while (row != null) {
            IRow SameRow = selectedTable.GetRow(row.OID); // DON'T DO THIS
            row.set_Value(fieldColumn, (double)SameRow.get_Value(fieldColumn) * 2);
            row.set_Value(fieldColumn+1, (double)SameRow.get_Value(fieldColumn) * 2);
            updateCursor.UpdateRow(row);
            row = _updateCursor.NextRow();
}

because SameRow will have the values of the row as it was before you updated the values; in some situations this may be what you want though, just remember you can't update SameRow because it didn't come from the cursor and you shouldn't Store SameRow while you have an update cursor in operation.

While you're updating rows with a cursor you have to be careful of grabbing rows as the modified rows are not necessarily written back to the table immediately, if you want to grab another row from the table using GetRow for some reason or even starting a Search (for example finding rows that match a field) you need to Flush the cursor to commit the changes to the table, which you should do periodically to clear used memory, this is also true for IFeatureCursor objects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.