Select to view content in your preferred language

AGOL honors Composite but not Simple Relationship class rules

1424
10
09-02-2021 12:44 PM
DougBrowning
MVP Esteemed Contributor

Came across this for Survery123 but posting here since it is a AGOL issue.

To review a Composite relationship class will "manage" the data.  Mainly if you delete a parent it will also delete the children.  This does seem to be honored in AGOL when editing hosted services.

A Simple class is considered "unmanaged" but that is not really true.  What Simple does is if you delete a parent all the children keys turn to Null.  (No idea why they would do that.  The big issue here is if you delete a few parents at once you can now not pull the children back apart.  Highly annoying BTW.)  The funny thing here is that AGOL is NOT honoring this rule like it does for Composite. 

No idea if this is a bug or what.  Anyone seen anything about this?  Anyone know why AGOL is diff than SDE?  I actually like it since Simple in AGOL does not null keys we are able to merge children more easily.  

As a side note

I use this trick to get around this management.  If you are not using the globalid for the relate (which you really should not) I first calculate the key field of the parent to the word Delete.  Then replicate if you have one.  Then delete the parents - this way when it goes looking for children with the key delete it finds none and all good.  The just replace the parents.

If you do use globalid (using built in 123 classes for example) then I instead change the children parentglobalid field to a value like delete.   Then when I delete the parent it cannot find any children and leaves it alone.  Then when I replace the parent I can fix the parentglobalids to the new parent.  Of course the hard part here is having a way to tell the children apart.  Need to delete one parent at a time or have a second field to hold some info that allows you to piece it back together.  This is why I always have my own key field in my data that I pass down to all my repeats.   Saves my butt on the reg.

Hope that helps someone.

10 Replies
AlfredBaldenweck
MVP Regular Contributor

Not to sidetrack your post too much, but you've mentioned not using GlobalID for relationships in a few other posts and I was wondering the best way to do that.

It seems like this(Database Sequneces) is the way to go about it for non-hosted features, but for Survey123, for example, how do you do it for the main table and any repeats?

Is it this (Ticket Problem)?

0 Kudos
DougBrowning
MVP Esteemed Contributor

My IDs are all pregenerated for this project because all the points are premade so that makes it easier.  I add all of these to Field Maps then just pass the id over to 123.  I then pass that id down to any repeats.  123 still does its thing with parentglobalid which is fine.  If either get messed up then other is there.  The main reason here is once you export and import to say SDE globalids fall apart.

If you mean you need to generate ids on the fly I use Arcade for that in another project.  This one they have preset locations but they go back multiple times.  So for each Visit I generate the id based on the Asset ID and the date.

Concatenate($feature.PointID, "_", text($feature.FieldEvalDate, "Y-MM-DD"))

Then I pass this id to the form.  

My guess is you are used to doing a ticket id in sequence.  Like it has to be 1, 2, 3, 4.  That is really hard when you have 100 people offline.   I do not know a way to solve that if offline so instead I generate the id using attributes and a time stamp.  The nice thing about that is that you can use contains later and query all the children of a parent so easy.

I hope that makes sense.

0 Kudos
AlfredBaldenweck
MVP Regular Contributor

It does, thank you.

It appears that there isn't really a way to make nice IDs, so I've been becoming more comfortable with ugly IDs.

Thanks!

0 Kudos
DougBrowning
MVP Esteemed Contributor

Agreed.  But one thing I have found is now that we give people relationship classes no one cares about the id much anymore.  They used to sit and query each table for ticket 6599 and now all they do is click show related and done.  Do not even notice the ID anymore.

If you really wanted Ids like that you could run a script each night that calculates it once they are all uploaded.  We do that sometimes to make the Id a real field vs Arcade.

DougBrowning
MVP Esteemed Contributor

Bump?

0 Kudos
DougBrowning
MVP Esteemed Contributor

Well today I found out that ANY edit to a child record will cause the PrimaryKey to go null if there is no parent record!  This is kinda crazy.  Why is it checking for a parent all the time?  Esp in a Simple relate it should NOT be managing it at all.

I can find nothing at all in the help on this.  We have some historical stuff and it is not complete yet is why we have this.

What is even weirder is it only does it on the replica and not in the DB that we actually do the edits.  So I edit in the base parent replica and no Keys are changed.  When I replicate to the one way child replica it turns the keys null there!  So there is some process going on after a replicate that checks all related keys.  No idea why it would do that, esp in a one way replica.

Anyone else seen this?

thanks

0 Kudos
ceverhart
New Contributor

@DougBrowning Hey Doug, I'm experiencing some weirdness going on with my relationship classes and found your article the most helpful. We have a feature service with a bunch of layers that were published with relationship classes. There are many parts to it but long story short when we delete a parent, some of the child relations' primary key is being nulled. No idea why considering it's ONLY on simple relations. Did you ever find a fix to this? 

DougBrowning
MVP Esteemed Contributor

Nope @ceverhart  we still battle it all the time - just yesterday even.  The only real work around I found is a post I should have linked back here.  Its simple yet genius.

If you want to safely delete a parent.

First field calc the key to something else in the parent records - I just use the word "Delete".

If you have a replica, replicate now so that the key gets changed in all replicas.  (Otherwise at the next step it will go south on you since it does not go in order.)

Now actually delete the parent records.  At this step it goes looking for all the children to turn them null.  But since the key was changed to "Delete" it does not find any children and does nothing.

If you have a replica, replicate again.

Then you can replace the parents with the proper keys and you should be all good.

This trick has been a total live saver!  Hope that helps

0 Kudos
DougBrowning
MVP Esteemed Contributor

Oh and it is buried on the ArcPro help now.  Now WHY they would make it do this makes no sense at all.

https://pro.arcgis.com/en/pro-app/latest/help/data/relationships/geodatabase-relationship-class-type... 

In a simple relationship, related objects can exist independently of each other. This means that deleting a destination object has no effect on the primary key value or on the parent record in the related origin table.  (right here is says no effect then down below it says oh yea we change to null)

For example, a report has come in that a recent storm has washed out Slough Creek campsite #6; therefore, deleting this record from the Campsite (destination) feature class has no effect on the Slough Creek Campground in the Campground Facilities (origin) feature class.

However, when you delete an origin object in a simple relationship, the foreign key field value for the matching destination object is set to <Null>. This foreign key behavior was designed to maintain referential integrity between features. If the origin feature is deleted, the value in the foreign key is no longer relating that row to a feature in the origin and, as a result, the foreign key value is no longer required and is set to Null.

The sole purpose of the foreign key is to maintain a relationship between the destination object and the related origin object. If there is no origin feature with the matching primary key value, there is no reason to maintain the foreign key value. If you want to relate the same destination feature to a new or different origin feature in the future, the foreign key field can be updated from <Null> to the new foreign key value.

0 Kudos