I'm creating an ArcMap toolbar that will be used to update a feature layer and related table in an SDE. As of now, I'm creating two edit sessions: one for the layer and one for the table — preferably, I could do it in one edit session. However, I get an error that the workspace is already in transaction when I try to insert a row into the related table.
The onClick method kicks off the attempt. It successfully runs the first start method (in Tiles), but fails with a transaction mode error for the second start method (in RelatedTable).
def editor(sub_function):
def _runner(*args, **kwargs):
edit = arcpy.da.Editor(Tiles.root())
result = None
try:
edit.startEditing(False, True)
edit.startOperation()
result = sub_function(*args, **kwargs)
success = True
except Exception as e:
print(traceback.format_exc())
success = False
finally:
if edit.isEditing:
edit.stopOperation()
edit.stopEditing(success)
del edit
return result
return _runner
def onClick(self):
result, tile_id, row = Tiles.start()
if result == Tiles.NO_ERROR:
result = RelatedTable.start(tile_id)
if result:
KeyMaster.tile_start()
else:
Tiles.revert_start(row)
elif result == Tiles.SELECTION_COUNT_INVALID:
send_message("Only one tile can be selected.", 'Error')
elif result == Tiles.SELECTION_VALUE_INVALID:
send_message('The tile must be "checked out" in your name before it can be started.', 'Error')
@classmethod
def start(cls):
@editor
def updater():
fields = [EditFields.user, EditFields.status, FieldNames.id]
tile_id, row = None, None
with arcpy.da.UpdateCursor(Tiles.get(), fields) as cursor:
for row in cursor:
if (row[0] == FieldValues.USERNAME) or KeyMaster.is_unlocked():
row[0] = FieldValues.USERNAME
row[1] = FieldValues.STARTED
tile_id = row[2]
cursor.updateRow(row)
return tile_id, row
fids = cls.fid_set()
if len(fids) != 1:
return Tiles.SELECTION_COUNT_INVALID, None, None
tile_id, row = updater()
if tile_id is not None:
return Tiles.NO_ERROR, tile_id, row
else:
return Tiles.SELECTION_VALUE_INVALID, None, None
@classmethod
def start(cls, tile_id):
@editor
def updater():
fields = [RelatedTable._userField,
RelatedTable._startField,
RelatedTable._idField,
RelatedTable._typeField]
with arcpy.da.InsertCursor(RelatedTable.get(), fields) as cursor:
row = [FieldValues.USERNAME,
datetime.datetime.now(),
tile_id,
EditFields.get_type()]
RelatedTable.set_fid(cursor.insertRow(row))
RelatedTable.set_id(tile_id)
return True
success = updater()
if success:
return Tiles.NO_ERROR
else:
return Tiles.SELECTION_COUNT_INVALID
Solved! Go to Solution.
Turns out that while the tiles feature class was set to versioned, the related table was not. Changing the related table to versioned fixed the error. Still would have been nice to have an error message that might have pointed toward this being the problem...
I suspect it is because you are trying to loop through an insertCursor. Just set the cursor to a variable, then insertRow(value).
This tech support article and this post should give you good enough example to see if that is the issue.
R_
InsertCursor is not being used in a loop. As the code's written, the InsertCursor is called in a completely different function well after UpdateCursor has fallen out of scope. I did try setting InsertCursor as a variable, but I'm getting the same problem.
Turns out that while the tiles feature class was set to versioned, the related table was not. Changing the related table to versioned fixed the error. Still would have been nice to have an error message that might have pointed toward this being the problem...