AnsweredAssumed Answered

Unexpected update cursor behavior affecting feature linked annotation

Question asked by rfairhur24 on Sep 11, 2014
Latest reply on Jan 27, 2016 by kesselbaump

I have been using code to transfer data from one source to another using a da update cursor.  However, I got an unexpected and very upsetting behavior when I included a field in the update cursor field list that acts as a trigger to change the feature linked annotation when it is updated.  This occurred on a versioned SDE feature class that requires the use of an edit operation to let the update cursor work.


The field was only included in the update cursor's field list to provide a look up key to another table.  No value changes or duplications were written to that Key field by the update cursor.  The update cursor only read values from the trigger field.  Updated values were only written to the other fields in the update cursor field list. 


Unfortunately, when I applied the updateRow action to the cursor for each row, the feature linked annotation had its TextValue update process triggered even though nothing had been written directly to the trigger field.  I also noticed that when the update process triggered an annotation update that the update cursor sent the record through my record processing loop twice.  Double processing of a record could have a severe impact on many cursor update operations. However, in this particular case it was only an issue because it slows down the update process.


This behavior moved the annotation objects and overwrote annotation values that had been intentionally manually altered.  This has corrupted my annotation feature class and I now am scrambling to get a backup restored.  It never occurred to me that the field would act as a trigger for annotation just because it was included in the update cursor field list and read.  Why is that behavior so different from the manual editing process, which only triggers an annotation update when the trigger field is altered or duplicated?


I have modified the code to exclude all fields involved in the update of feature linked annotation, since I had another field that contained look up values related to the external table.  By excluding all fields that can trigger annotation updates the update cursor does affect the annotation of the feature class.  Also the records are processed just once by the cursor loop as well.  I had also used similar code on the same feature class before and only when the trigger field was in the update field list did the cursor trigger the annotation to update.


However, what if I had no alternative field availalbe and had to use the trigger field for the look up value?  Disabling the feature linked update behavior seems to be the only solution in that case,  I just wish I had known about this behavior before reconciling all of my versions.  Is this behavior adequately documented?  I don't recall reading or hearing about it.


Here is the code in case anyone thinks I must have actually written updated values to the trigger field.  The field that can trigger the feature linked annotation to update itself is called STNAME.


import arcpy
import os
from time import strftime

sourceFC = r"C:\Users\RFAIRHUR\AppData\Roaming\ESRI\Desktop10.2\ArcCatalog\Trans Connection to SQL Server.sde\MasterStreetName"
updateFC = r"C:\Users\RFAIRHUR\AppData\Roaming\ESRI\Desktop10.2\ArcCatalog\Trans Connection to SQL Server.sde\GDB_TRANS.TRANS.TRANSPORTATION_MAINT\CENTERLINE"

print "Make Feature Layer: " + strftime("%Y-%m-%d %H:%M:%S")
arcpy.MakeFeatureLayer_management(updateFC, "CENTERLINE_Layer")
arcpy.SelectLayerByAttribute_management("CENTERLINE_Layer", "NEW_SELECTION", "FULL_NAME_MIXED_CASE IS NULL")
records = int(arcpy.GetCount_management("CENTERLINE_Layer").getOutput(0))
while records >= 1:
    print str(arcpy.GetCount_management("CENTERLINE_Layer")) + " Records Selected: " + strftime("%Y-%m-%d %H:%M:%S")
    updateFC = "CENTERLINE_Layer"

    workspace = r"C:\Users\RFAIRHUR\AppData\Roaming\ESRI\Desktop10.2\ArcCatalog\Trans Connection to SQL Server.sde"

    sourceFieldsList = ["FULLNAME_ALL_CAPS", "FULLNAME"]  
    updateFieldsList = ["STNAME", "FULL_NAME_MIXED_CASE"]
    valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(sourceFC, sourceFieldsList)}  

    edit = arcpy.da.Editor(workspace)  
    edit.startEditing(False, True)   

    i = 0  
    with arcpy.da.UpdateCursor(updateFC, updateFieldsList) as updateRows:  
        for updateRow in updateRows:  
            i += 1
            if i % 101 == 0:
            keyValue = updateRow[0]  
            if keyValue in valueDict:  
                for n in range (1,len(sourceFieldsList)):    
                    updateRow[n] = valueDict[keyValue][n-1]  
    del valueDict   
    arcpy.SelectLayerByAttribute_management("CENTERLINE_Layer", "NEW_SELECTION", "FULL_NAME_MIXED_CASE IS NULL")
    records = int(arcpy.GetCount_management("CENTERLINE_Layer").getOutput(0))
print "Finished All Records: " + strftime("%Y-%m-%d %H:%M:%S")