Hi,
Problem
currently we are using the applyEdits function of the featureLayer.
Unfortunately we now face the following problem:
When this is sent via applyEdits the execution order seems random or maybe by uid.
This leads to the not-yet-main-address to be given the main-address attribute first before the main-address attribute is revoked from the original mainAddress.
Means there are two main-addresses at once violating the attribute rule and thus aborting the transaction.
ApplyEdits: FeatureService vs. FeatureLayer
We are using
featureLayer.applyEdits()There are two different applyEdits APIs:
Unfortunately they behave different.
The FeatureService offers this param:
FeatureServiceApplyEditsOptions.honorSequenceOfEditsWhich is not available for:
FeatureLayerApplyEditsOptions
Additionally their edits JSON are built differently as far as I understood documentation.
Searching for Solution
Workaround 1 (not suitable)
I would not like to split this into two different transactions. In case one excepts the other cannot be invalidated any more.
Question1
Is there any way to allow sequence order for featureLayer.applyEdits too?
Question2
How do I use FeatureService applyEdits in Arc JS? The FeatureLayer to perform for + applyEdits JSON from FeatureLayer.applyEdits is given
Examples I found so far only describe the FeatureLayer applyEdits.
I found this sample:
https://developers.arcgis.com/arcgis-rest-js/api-reference/arcgis-rest-feature-service/applyEdits/
import { applyEdits } from '@esri/arcgis-rest-feature-service';
//
applyEdits({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0",
adds: [{
geometry: { x: -120, y: 45, spatialReference: { wkid: 4326 } },
attributes: { status: "alive" }
}],
updates: [{
attributes: { OBJECTID: 1004, status: "alive" }
}],
deletes: [862, 1548]
})
.then(response)
Question3
Is there may another way for the AttributeRule to be postponed to the end of the transaction after all edits were done in place but right before the changes will be persisted.
But the stated import does not work, erros are given, that it cannot be found.
I am using arcgisCore 4.34
Solved! Go to Solution.
This is useful thank you.
I was able to reproduce and I do see what is going on. HonorSequenceOfEdits controls the outside layer edits payload, not the individual edits within a layer. As you may have noticed, the array of updates within a single edit are ordered by objectId and executed in ascending order (lowest objectid first). So in your example, objectid 61818 is updated first, followed by 71416 which is made into a main address, resulting in the failure, because 71816 was not updated yet.
If you want to force the 3 updates to be in executed in the order, you will just need to change the payload from one edit with 3 updates to 3 edits each with a single update. They will still be in a single transaction, but 3 distinct edits to the same layer instead.
Here is your applyEdits (simplified) before and after the change.
//one edit, 3 updates
[{
"id": 21,
"updates": [{
"attributes": {
"objectid": 71816,
"globalid": "{0539CB83-A63B-4ED2-9502-398A414DB666}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}, {
"attributes": {
"objectid": 71416,
"globalid": "{528C37D9-A398-4EC2-9AB4-027754F456B3}",
"object_address_type": 1,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}, {
"attributes": {
"objectid": 61818,
"globalid": "{F37ED8AD-3D2B-4B8A-BB93-9DAD47B512FC}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
}
]
Change it to
//3 edits, one update in each.
[{
"id": 21,
"updates": [{
"attributes": {
"objectid": 71816,
"globalid": "{0539CB83-A63B-4ED2-9502-398A414DB666}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
},
{
"id": 21,
"updates": [ {
"attributes": {
"objectid": 71416,
"globalid": "{528C37D9-A398-4EC2-9AB4-027754F456B3}",
"object_address_type": 1,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
},
{
"id": 21,
"updates": [ {
"attributes": {
"objectid": 61818,
"globalid": "{F37ED8AD-3D2B-4B8A-BB93-9DAD47B512FC}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
}
]
This payload should solve this issue.
Here is my repro case before and after the applyEdits change
after the change it works
Question2
How do I use FeatureService applyEdits in Arc JS? The FeatureLayer to perform for + applyEdits JSON from FeatureLayer.applyEdits is given
Examples I found so far only describe the FeatureLayer applyEdits.
Please read below for a code snippet showing how to leverage FeatureService.applyEdits.
BTW, FeatureService.applyEdits doc does include a code snippet (It only shows how to add features to a single layer though).
import Graphic from "esri/Graphic";
import FeatureService from "esri/rest/featureService/FeatureService";
const featureServerUrl = "https://myServer/server/rest/services/myService/FeatureServer";
const featureService = new FeatureService({
url: featureServerUrl,
});
const pointGraphic = new Graphic({
geometry: {
type: "point",
spatialReference: { wkid: 4326 },
longitude: 0,
latitude: 3,
},
// attributes: {},
});
const lineGraphic = new Graphic({
geometry: {
type: "polyline",
spatialReference: { wkid: 4326 },
paths: [
[
[0, 3],
[2, 5],
],
],
},
// attributes: {},
});
const edits = [
{
id: 1,
addFeatures: [lineGraphic],
// updateFeatures: [],
// deleteFeatures: []
},
{
id: 0,
addFeatures: [pointGraphic],
// updateFeatures: [],
// deleteFeatures: []
},
];
const serviceEditsOptions = {
// gdbVersion: "OWNER.VersionName",
honorSequenceOfEdits: true,
};
if (!featureService.loaded) {
await featureService.load();
}
featureService.applyEdits(edits, serviceEditsOptions).then((result) => {
console.log("featureService.applyEdits - result", result);
});
Thanks, I was able to call the featureService applyEdits.
Unfortunately the parameter honorSquence is not working as I expect.
FeatureA is being set as MainAddress.
I am changing this such that instead FeatureB is set as MainAddress.
The updateFeatures contains [A, B] (in this sequence) where MainAddress is set to 0 for A and set to 1 for B.
Unfortunately our AttributeRule is still violating saying that there must not be more than one Feature with MainAddress = 1.
This is how I am doing currently:
async applyEditsFeatureServiceAsync(featureLayer: FeatureLayer, editParams: __esri.FeatureServiceApplyEditsEdits, optionParams?: __esri.FeatureServiceApplyEditsOptions): Promise<boolean> {
let optionParams: __esri.FeatureServiceApplyEditsOptions = {
globalIdUsed: false,
honorSequenceOfEdits: true
};
editParams.id = featureLayer.layerId;
const featureService = new FeatureService({
url: featureLayer.url
});
if (!featureService.loaded) {
await featureService.load();
}
const editResults = await featureService.applyEdits([editParams], optionParams);Am I getting the parameter honorSequenceOfEdits wrong or would you agree that it should work?
Hi Sebastian,
Would it be possible to post the REST request that is generated from the `featureService.applyEdits` call? (Using debug tools, fiddler, etc.). That would let us see if the problem is occurring client or server side.
Thanks!
--Rich
here you are
edits:
"object_address_type" is the object where the attributeRule checks on.
"Herweg 3" (the first of the three) is currently being the MainAddress with "object_address_type" = 1.
During the edits you can see it is set to 0 and it is the very first in sequence before the second item is set as new MainAddress.
[{
"id": 21,
"adds": null,
"updates": [{
"attributes": {
"objectid": 71816,
"globalid": "{0539CB83-A63B-4ED2-9502-398A414DB666}",
"object_address_id": "{f0f1620d-b201-47ad-8295-9f1bb089e777}",
"from_address_id": "{54D1EBA5-8F37-4B19-94A5-E77DB2260C8A}",
"to_address_id": null,
"thoroughfare_id": null,
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}",
"created_user": "myuser",
"created_date": 1769081983000,
"last_edited_user": "myuser",
"last_edited_date": 1769081998000,
"relationLayerTitle": "Objekte Adressen",
"enhanced_from_address": "Herweg 3",
"enhancementLayerTitle": "AddressLayerTitle"
}
}, {
"attributes": {
"objectid": 71416,
"globalid": "{528C37D9-A398-4EC2-9AB4-027754F456B3}",
"object_address_id": "{2776a7d1-5c60-41dd-9e3b-002d2c06a45e}",
"from_address_id": "{EFA5BBDE-CF8C-4C24-9120-706E2EC8958D}",
"to_address_id": null,
"thoroughfare_id": null,
"object_address_type": 1,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}",
"created_user": "myuser",
"created_date": 1768991993000,
"last_edited_user": "myuser",
"last_edited_date": 1769081998000,
"relationLayerTitle": "Objekte Adressen",
"enhanced_from_address": "An der Bundesstraße 1",
"enhancementLayerTitle": "AddressLayerTitle"
}
}, {
"attributes": {
"objectid": 61818,
"globalid": "{F37ED8AD-3D2B-4B8A-BB93-9DAD47B512FC}",
"object_address_id": "{30B1EA83-C497-43AD-8EA2-D00DF7C83257}",
"from_address_id": "{25A3F94D-F02B-4F1B-A147-D8508D086D55}",
"to_address_id": null,
"thoroughfare_id": null,
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}",
"created_user": "Test",
"created_date": 1761214382000,
"last_edited_user": "myuser",
"last_edited_date": 1769081998000,
"relationLayerTitle": "Objekte Adressen",
"enhanced_from_address": "An der Bundesstraße 2",
"enhancementLayerTitle": "AddressLayerTitle"
}
}
],
"deletes": null,
"attachments": null
}
]
And here is the reponse referring to the attribute rule:
{
"error": {
"code": 400,
"extendedCode": -2147207418,
"message": "Unable to complete operation.",
"details": [
"Objekt fehlt.",
"Interner Fehler während Objektaktualisierung. Attributbedingungsregel wurde verletzt. [\nRegelname: Hauptadresse prüfen,\nAuslösendes Ereignis: Aktualisieren,\nKlassenname: ObjectAddress,\nGlobalID: {528C37D9-A398-4EC2-9AB4-027754F456B3},\nFehlernummer: 23,\nFehlermeldung: Es darf nur eine Hauptadresse zu einem Objekt existieren.]",
"Operation wurde zurückgesetzt."
]
}
}
And this is the actual AttributeRule:
var fs = FeatureSetbyName($datastore, "my.domain.ObjectAddress");
var fk = $feature.object_id;
if (isEmpty(fk))
{return true}
return count(Filter(fs, 'object_id = @fk and object_address_type = 1')) < 2We tried to check/uncheck the parameter "Exclude from application evaluation" but that did not make any difference.
This is useful thank you.
I was able to reproduce and I do see what is going on. HonorSequenceOfEdits controls the outside layer edits payload, not the individual edits within a layer. As you may have noticed, the array of updates within a single edit are ordered by objectId and executed in ascending order (lowest objectid first). So in your example, objectid 61818 is updated first, followed by 71416 which is made into a main address, resulting in the failure, because 71816 was not updated yet.
If you want to force the 3 updates to be in executed in the order, you will just need to change the payload from one edit with 3 updates to 3 edits each with a single update. They will still be in a single transaction, but 3 distinct edits to the same layer instead.
Here is your applyEdits (simplified) before and after the change.
//one edit, 3 updates
[{
"id": 21,
"updates": [{
"attributes": {
"objectid": 71816,
"globalid": "{0539CB83-A63B-4ED2-9502-398A414DB666}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}, {
"attributes": {
"objectid": 71416,
"globalid": "{528C37D9-A398-4EC2-9AB4-027754F456B3}",
"object_address_type": 1,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}, {
"attributes": {
"objectid": 61818,
"globalid": "{F37ED8AD-3D2B-4B8A-BB93-9DAD47B512FC}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
}
]
Change it to
//3 edits, one update in each.
[{
"id": 21,
"updates": [{
"attributes": {
"objectid": 71816,
"globalid": "{0539CB83-A63B-4ED2-9502-398A414DB666}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
},
{
"id": 21,
"updates": [ {
"attributes": {
"objectid": 71416,
"globalid": "{528C37D9-A398-4EC2-9AB4-027754F456B3}",
"object_address_type": 1,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
},
{
"id": 21,
"updates": [ {
"attributes": {
"objectid": 61818,
"globalid": "{F37ED8AD-3D2B-4B8A-BB93-9DAD47B512FC}",
"object_address_type": 0,
"object_id": "{9BE6E41A-8558-4268-B6B3-FB96A755B98D}"
}
}
]
}
]
This payload should solve this issue.
Here is my repro case before and after the applyEdits change
after the change it works
Thanks @HusseinNasser2 that is super helpful and should solve the problem!
@SebastianKrings , I checked with the developer who wrote `featureService.applyEdits` and we were able to confirm that if you pass three separate edits into the JavaScript routine, it should generate a REST call like Hussein specifies above.
I hope this helps!
--Rich
Great that works.
One more question:
When having these three edits instead of an single edit, will the three edits always be processed in this order or only when HonorSequenceOfEdits ist enabled?
Correct, you need HonorSequenceOfEdits to be set to true to respect the array order in the applyEdits. Otherwise if that parameter is false or not provided, we will use the layerId order, which in your case it will be non-deterministic since all of them are same layer
more on the doc
https://developers.arcgis.com/rest/services-reference/enterprise/apply-edits-feature-service/
gotcha
Maybe the doc should be extended by a sample showing the different means of multiple features within one "edit"-object and multiple "edit"-objects within the "edits"-array