Select to view content in your preferred language

Calculation Attribute Rules that check $originalFeature geometry against newly created features do no trigger on Insert

1936
4
Jump to solution
03-01-2022 12:56 AM
Jake_S
by Esri Contributor
Esri Contributor

When creating an ArcGIS Pro Calculation Attribute Rule that is triggered by an insert or update, if that includes a check of the geometry ($originalFeature) the rule does not trigger on insert.

The code below is intended to trigger on insert and update. Applied to the $feature, it updates a field value based on an intersecting feature class. It should, in theory, populate on insert or update.

 

if (Equals(Geometry($originalFeature),Geometry($feature))) {
    return $feature.SBPI_ID_NO
}
var parcels = Filter(Intersects(FeatureSetByName($datastore, "Parcel", ["RETIREDBYRECORD", "SBPI_ID_NO"], false), Centroid($feature)),'RETIREDBYRECORD IS NULL')
if (Count(parcels) > 0) {
    var select = first(parcels)
    return select.SBPI_ID_NO;
}
return null

 

The assumption is that when you create a new feature the $originalFeature geometry there is NULL (nonexistent) and when compared to $feature, which is assumed to be the new features geometry, the rule will trigger. To clarify, if geometry null/nonexistent is not equal to the new shape geometry the rule should trigger on insert. Because of the design of feature creation in Esri geodatabase (fGDB or eGDB) attribute rules that utilize $originalFeature on insert do not see a geometry change during creation and do not populate attributes.

This may indicate that during feature creation there is a ‘temporary’ object in which the geodatabase utilizes to calculate the features geometry, then the feature is created permanently in the geodatabase. The assumption is that the rule sees that there is a geometry (temporary object) and that geometry has not changed when creating the permanent geodatabase feature which the user sees.

We had to create a separate attribute rule without $originalFeature geometry to trigger on insert only. Then utilize the attribute rule below with the $originalFeature to trigger on update if there is a change to the geometry.

 

 

 

 

var parcels = Filter(Intersects(FeatureSetByName($datastore, "Parcel", ["RETIREDBYRECORD", "SBPI_ID_NO"], false), Centroid($feature)),'RETIREDBYRECORD IS NULL')
if (Count(parcels) > 0) {
    var select = first(parcels)
    return select.SBPI_ID_NO;
}
return null

 

 

 

 

 

Is this a common issue? Are we utilizing the $originalFeature global incorrectly? Can we confirm that this is in fact how features are created in a Esri Geodatabase?

0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

I did a quick test, your rule works for me, both in FGDB and SDE.

Possible workarounds:

  • You can use the $editcontext.editType global
  • The includeGeometry flag of FeatureSetByName should probably be true. I'm actually surprised it works when set to false, because (if I understand it correctly) there shouldn't be any geometry for the Intersects...
  • There's nothing wrong with using separate rules for insert and update. Yes, code duplication can be a bit troublesome, but having (different) insert and update procedures in the same rule can also get confusing.
// only compare with original geometry when you update, not on insert
if ($editcontext.editType == "UPDATE" && Equals(Geometry($originalFeature),Geometry($feature))) {
    return $feature.SBPI_ID_NO
}
 // set includeGeometry to true
var parcels = Filter(Intersects(FeatureSetByName($datastore, "Parcel", ["RETIREDBYRECORD", "SBPI_ID_NO"], true), Centroid($feature)),'RETIREDBYRECORD IS NULL')
if (Count(parcels) > 0) {
    var select = first(parcels)
    return select.SBPI_ID_NO;
}
return null

 


Have a great day!
Johannes

View solution in original post

4 Replies
JohannesLindner
MVP Frequent Contributor

I did a quick test, your rule works for me, both in FGDB and SDE.

Possible workarounds:

  • You can use the $editcontext.editType global
  • The includeGeometry flag of FeatureSetByName should probably be true. I'm actually surprised it works when set to false, because (if I understand it correctly) there shouldn't be any geometry for the Intersects...
  • There's nothing wrong with using separate rules for insert and update. Yes, code duplication can be a bit troublesome, but having (different) insert and update procedures in the same rule can also get confusing.
// only compare with original geometry when you update, not on insert
if ($editcontext.editType == "UPDATE" && Equals(Geometry($originalFeature),Geometry($feature))) {
    return $feature.SBPI_ID_NO
}
 // set includeGeometry to true
var parcels = Filter(Intersects(FeatureSetByName($datastore, "Parcel", ["RETIREDBYRECORD", "SBPI_ID_NO"], true), Centroid($feature)),'RETIREDBYRECORD IS NULL')
if (Count(parcels) > 0) {
    var select = first(parcels)
    return select.SBPI_ID_NO;
}
return null

 


Have a great day!
Johannes
Jake_S
by Esri Contributor
Esri Contributor

Johannes,

Thanks for taking a look. I'll explore your solution. 

To my understanding includeGeometry flag should be set 'true' when you are modifying the features geometry. This concept is outlines in this video at about the 13 min mark.

Again thanks so much!

-Jake

JohannesLindner
MVP Frequent Contributor

That's a very helpful video, that I missed completely, thanks!


Have a great day!
Johannes
0 Kudos
Jake_S
by Esri Contributor
Esri Contributor

@JohannesLindner Was able to test this and works like a charm. Also tested with includeGeometry flag set to false and executed. 

0 Kudos