[GIS] Having trouble nesting updatecursors

arcpyupdate

I'm trying unsuccessfully to perform updates on multiple linked tables using updatecursors.

The following code works as I would expect:

trackRows = arcpy.SearchCursor("tracks","Key_='b2879561-d751-e111-9e92-0050568e18a0'")
for trackRow in trackRows:
    arcpy.management.MakeFeatureLayer("tracks","currentTrack","Key_='" + str(trackRow.Key_) + "'")
    grXingRows = arcpy.SearchCursor(GradeCrossings,"LinkKey='" + str(trackRow.Key_) + "'");
    for grxrow in grXingRows:
        inspectionRows = arcpy.SearchCursor(Inspections,"LinkKey='" + str(grxrow.getValue("Key_")) + "'")
        for insprow in inspectionRows:
            grxDefRows = arcpy.UpdateCursor(GradeCrossingDefects,"LinkKey='" + str(insprow.getValue("Key")) + "'")
            for grxdefrow in grxDefRows:
                grxdefrow.LocationVal = 7
                grxDefRows.updateRow(grxdefrow)
            del(grxDefRows)
        del(insprow)
    del(grXingRows)
    arcpy.management.Delete("currentTrack")

However, when I change the 4th line to use arcpy.UpdateCursor, the script still runs, but the data rows that are updated in the inner loop don't get updated in the DB.

Any ideas?

EDIT: Having tested out the suggestions about deleting cursors and rows more thoroughly, I now have the following:

trackRows = arcpy.SearchCursor("tracks","Key_='b2879561-d751-e111-9e92-0050568e18a0'")
for trackRow in trackRows:
    arcpy.management.MakeFeatureLayer("tracks","currentTrack","Key_='" + str(trackRow.Key_) + "'")
    grXingRows = arcpy.UpdateCursor(GradeCrossings,"LinkKey='" + str(trackRow.Key_) + "'");
    for grxrow in grXingRows:
        inspectionRows = arcpy.SearchCursor(Inspections,"LinkKey='" + str(grxrow.getValue("Key_")) + "'")
        for insprow in inspectionRows:
            grxDefRows = arcpy.UpdateCursor(GradeCrossingDefects,"LinkKey='" + str(insprow.getValue("Key")) + "'")
            for grxdefrow in grxDefRows:
                grxdefrow.LocationVal = 7
                grxDefRows.updateRow(grxdefrow)
                del(grxdefrow)
            del(grxDefRows)            
            del(insprow)
        del(inspectionRows)
        del(grxrow)
    del(grXingRows)
    arcpy.management.Delete("currentTrack")
    del(trackRow)
del(trackRows)

Still no luck! I tried deleting the rows within the loop, and tried deleting the rows outside of the loop. Neither solved my problem.

EDIT: Now I feel a little silly. I had a map service running which was maintaining a lock on BOTH of the feature classes I was trying to update. I used arcpy.TestSchemaLock to test, and found that it returned false for both feature classes regardless of whether the first was using a searchcursor or an updatecursor. Stopping the service solved my issue. However there is still some funny behavior here that I'd like to understand:

  1. According to the documentation, if the updatecursor can't get an exclusive lock, then it should error out…but my script ran just fine, no errors…why?
  2. Even given that not erroring were a valid behavior, I still should not have been successful with the inner update EVER when the service was running, but it worked fine as long as it was the only updatecursor I was using. Why?

EDIT: After sleeping on it and trying again, it seems the success from 2 days ago was a fluke. Both yesterday and today I have been unable to get the script to update the database correctly. The script is unchanged, and I have checked to ensure that there are no schemalocks on these feature classes (TestSchemaLock returns true). I'm not sure what stars had aligned which are now misaligned, but I still have no solution to the problem.

Best Answer

Your issue has to do with the Locking action that happens when an UpdateCursor is called. From the help document:

Summary

The UpdateCursor function creates a cursor that lets you update or delete rows on the specified feature class, shapefile, or table. The cursor places a lock on the data that will remain until either the script completes or the update cursor object is deleted.

What that means to me is that if you call an UpdateCursor in the 4th line, then it puts a lock on the data layers that persists and blocks the UpdateCursor you have inside your loop from working. Since you can update many different parts of the feature with this Cursor, including feature geometry, or attribute information, it stands to reason that having a Linked Table in the Cursor will cause a lock to be placed on both tables involved in the join.

The other factor coming into play is the locking of datasets during editing. If the two featureclasses you are trying to update are located in the same Feature Dataset, then even if they are not linked in the Cursor, they would both be locked. Here is some additional information on Schema Locking.

Related Question