The Evaluation of attribute rule is cyclic or exceeds maximum cascading level.

536
1
Jump to solution
07-21-2023 12:36 PM
Labels (1)
Skysurfer
New Contributor II

I am trying to create an attribute rule that updates the GIS_PropertyAcres field across all features that all share a common Parent Property ID when the geometry of a feature is updated. I am constantly getting a  Does anyone know how to modify the following code to prevent this error from occurring?

 

//Creates empty array and counter for iterating
var updates = []
var counter = 0
var id = $feature.ParentPropertyID
var fs = Filter($featureset, "ParentPropertyID = @ID")
var newacres = Sum(fs, "GIS_TractAcres")
var new_shape_area = $feature.Shape_Area
var old_shape_area = $originalfeature.Shape_Area
var cnt_poly = count(fs)

if (new_shape_area != old_shape_area){
   for (var f in fs){
    updates[counter] = { 
            'globalid': f.GlobalId,
            'attributes':{
                'GIS_PropertyAcres': newacres,      
            } 
        }
		counter++ 
    }  
    return {
        'edit': [{
            'className': 'Arcade_Rules_Test',
            'updates': updates
        }]
    }
 }

else {
   return $originalfeature.GIS_PropertyAcres 
}

 

Screenshot 2023-07-21 150334.png

1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

When you return a dictionary with update instructions, these updates trigger the rule again. You have it set up so that the same feature gets updated over and over and over, so at some point ArcGIS halts the loop and errors out.

I think you have the right idea in line 11: You need to check whether the attribute you care about was changed by the update. If not, you don't need to return further update instructions. I'm not really sure why your condition isn't working, and I honestly don't feel like diving too deep into it...

Anyway, here is an expression that should work as expected. It updates both GIS_TractAcres and GIS_PropertyAcres, so you only need this one rule. It also handles deleting features properly.

// Calculation Attribute Rule
// field: empty
// triggers: Insert, Update, Delete
// exclude from application evaluation


var mode = $editcontext.editType

// abort if this is an update that doesn't change the geometry
if(mode == "UPDATE" && Equals(Geometry($feature), Geometry($originalfeature))) {
    return
}

// get all OTHER features with this ID
var id = $feature.ParentPropertyID
var gid = $feature.GlobalID
var query = "ParentPropertyID = @ID AND GlobalID <> @gid"
var fs = Filter($featureset, query)

// get this area and the sum of the other areas
var f_area = Area($feature, "acres")
var total_area = Sum(fs, "GIS_TractAcres")

// if this is an insert or update, add this area to the total (don't do it if this is a delete)
if(mode != "DELETE") {
    total_area += f_area
}

// construct the update array
var updates = []
for(var f in fs) {
    if(f.GlobalID == $feature.GlobalID) { continue }
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            GIS_PropertyAcres: total_area
            }
        }
    Push(updates, u)
}

return {
    result: {
        attributes: {
            GIS_TractAcres: f_area,
            GIS_PropertyAcres: total_area}
        },
    edit: [{
        className: "Arcade_Rules_Test",
        updates: updates
        }]
}

Have a great day!
Johannes

View solution in original post

0 Kudos
1 Reply
JohannesLindner
MVP Frequent Contributor

When you return a dictionary with update instructions, these updates trigger the rule again. You have it set up so that the same feature gets updated over and over and over, so at some point ArcGIS halts the loop and errors out.

I think you have the right idea in line 11: You need to check whether the attribute you care about was changed by the update. If not, you don't need to return further update instructions. I'm not really sure why your condition isn't working, and I honestly don't feel like diving too deep into it...

Anyway, here is an expression that should work as expected. It updates both GIS_TractAcres and GIS_PropertyAcres, so you only need this one rule. It also handles deleting features properly.

// Calculation Attribute Rule
// field: empty
// triggers: Insert, Update, Delete
// exclude from application evaluation


var mode = $editcontext.editType

// abort if this is an update that doesn't change the geometry
if(mode == "UPDATE" && Equals(Geometry($feature), Geometry($originalfeature))) {
    return
}

// get all OTHER features with this ID
var id = $feature.ParentPropertyID
var gid = $feature.GlobalID
var query = "ParentPropertyID = @ID AND GlobalID <> @gid"
var fs = Filter($featureset, query)

// get this area and the sum of the other areas
var f_area = Area($feature, "acres")
var total_area = Sum(fs, "GIS_TractAcres")

// if this is an insert or update, add this area to the total (don't do it if this is a delete)
if(mode != "DELETE") {
    total_area += f_area
}

// construct the update array
var updates = []
for(var f in fs) {
    if(f.GlobalID == $feature.GlobalID) { continue }
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            GIS_PropertyAcres: total_area
            }
        }
    Push(updates, u)
}

return {
    result: {
        attributes: {
            GIS_TractAcres: f_area,
            GIS_PropertyAcres: total_area}
        },
    edit: [{
        className: "Arcade_Rules_Test",
        updates: updates
        }]
}

Have a great day!
Johannes
0 Kudos