Appending to child layers in feature services with attachments

12-14-2021 03:41 PM
Labels (3)
Occasional Contributor

Taking off on the thread found at: in regard to appending to feature services while maintaining attachment and relationships. Here are the steps I am using to accomplish this. I understand that modifying a local full version of the database and overwriting it to accomplish updates may be offered as a work around. This is less than desirable as a work around because of the potentially large upload sizes, and the inherent risk involved in replacing that many records in bulk. What I detail here is a method for updating parent and child feature service layers in ArcGIS Online through a detailed append operation. 

Needed is a destination feature service with at least one parent-child relationship and attachments enabled on both layers. Each layer will also need an additional GUID type field for storing temporary global id's as part of the append process.

The source features an be local FGDB layers or feature services with attachments. While the parent layer can be successfully appended from either a local or another feature service source with attachments intact, none of the child layers will successfully append with attachments intact.

9999 error on append.png

In order to make the append with attachments and relationships I follow these steps:

  1. Identify by selection in a feature service the source features to append. Calculate the feature global id into the temporary GUID field to preserve the value. Export to a local FGDB with maintain global ids enabled (maintain global id's should work for this step and this step only). Be sure to have maintain attachments enabled.
  2. Append the parent layer from the feature service selection or the local FGDB. Do not check maintain Global ID's, as this will cause failure. Do check maintain attachments. Use the field map option if field names do not match between source and target.
  3. For the child layers, the append occurs in two passes, one for features, another for attachments. Append the selected child features without the maintain attachments or maintain global id's enabled as these cause failure. The values in the parentglobalid field of the child layer will be preserved, and will match the values in the temporary GUID field on the parent layer.
  4. Join the child layer to the parent layer by matching the temporary GUID field on the parent layer to the parentglobalid field on the child layer and validate the join to ensure you get a reasonable number of matches. Calculate the new parent global id value into the temporary GUID field on the child layer. Calculating into the parentglobalid field will cause error as the join is based on that field.
  5. Remove the join. Calculate the GUID values in the temporary field on the child layer into the parentglobalid field. These values will now match to a parent feature.
  6. Remove the attachments from the child layer (recall parent attachments should have transferred with that append). To do this, I modified the code found in this technical article:
  7. import arcpy
    from arcpy import da
    import os
    import csv

    = arcpy.GetParameterAsText(0)
    inTable_RelField = arcpy.GetParameterAsText(1)
    fileLocation = arcpy.GetParameterAsText(2)
    out_csv = arcpy.GetParameterAsText(3)
    out_csv_full = os.path.join(fileLocation, out_csv)
    with open(out_csv_full, 'w', newline='') as csvfile:
        csv_writer = csv.writer(csvfile)
        csv_writer.writerow(["ATT_NAME", "ATTACHMENTID", "Feature_ID", "Image_Path"])
        with da.SearchCursor(inTable, ['DATA', 'ATT_NAME', 'ATTACHMENTID', inTable_RelField]) as cursor:
            for item in cursor:
                attachment = item[0]
                filenum = "ATT" + str(item[2]) + "_"
                filename = filenum + str(item[1])
                arcpy.AddMessage("Filename: {} \n Filenum: {}".format(filename, filenum))
                image_Path = fileLocation + os.sep + filename
                csv_writer.writerow([str(item[1]), str(item[2]), str(item[3]), image_Path])
                open(fileLocation + os.sep + filename, 'wb').write(attachment.tobytes())
                del item
                del filenum
                del filename
                del attachment
  8. Which could absolutely be improved upon but does have the helpful feature of creating the file needed to use the Add Attachments tool.
  9. Add the attachments using the add attachments tool. Note that the tool requires a local copy of the layer and attachments table. Note too that the attachment table relates to the child layer via the REL_GLOBALID field. This value will now have changed in the feature service with the append of the selected child features. To update the global id's in the REL_GLOBALID field, calculate the new global id values for the child features into the temporary GUID field. Use Feature to Point tool and Intersect the points by the child features (or use spatial join). Use the resultant feature to join onto the attachments export table and the appended feature service child features (using ORIG_FID and the local child layer ObjectID, for instance), and update the REL_GLOBALID field to match the values in the global id field of the desired target feature service child features.
  10. Use the Add attachments tool, referencing the updated table and the attachments folder.

I've experienced parallel behavior trying to use the Update Data on the feature service details overview page where the parent layer will update, but related child layers will fail to append properly.

The above method, while doable, is pretty heroic in level of effort compared to the idea of just using the append tool with maintaining attachments, and, ideally, some more automated method for updating the appended relationship keys. Is that something that is in the development pipeline?

Thanks for reading this far!

0 Replies