QueryTask.ExecuteRelationshipQueryAsync - editing the related records

954
7
08-24-2010 03:01 PM
BrooksShannon
New Contributor
I have a (hopefully) easy question about feature relationships, and editing records that participate in a relationship with a feature class.

I notice that the QueryTask exposes an ExecuteRelationshipQueryAsync method. This apparently lets you access records related to a given feature (or set of features).  I'm thinking of using this to access records that exist in a simple 1:M relationship: one point feature related to 0 or more records in a Table (not a feature class, specifically).

It seems that the QueryTask.ExecuteRelationshipQueryAsync() method would be the ticket to accessing the related records.  That would get me half-way to where I need to be. What I'd really like to do is make edits to those related records - the full suite of CRUD operations. 

I don't need to use the FeatureDataForm / Grid / etc to pull this off, necessarily - it's quite likely that I'll roll my own custom UI to do this.  That would give me the ability to do some legwork under the hood to commit the edits, if I had to.  Since the result of the ExecuteRelationshipQueryAsync operation, at the end of the day, is a RelationshipResult instance, I can get at the related records (as Graphics), and could easily make changes to their attributes.

It's the next step that I can't quite figure out.  Once I've made my changes, I have to be able to save my edits. In addition, I'll have to be able to add and remove related records.  To do that, I suppose that I'll need a feature layer; one that represents the table containing my related records.  I can put that together, of course, without much trouble.

The question then, is this: will my edits be committed if I, say, change the attributes of a Graphic in the RelationshipResult.RelatedRecordsGroup and then call SaveEdits() on the feature layer that represents the related table?  Or do I need to do something like inspect the Graphics in the RelationshipResult.RelatedRecordsGroup, and then go retrieve them again from my feature layer, and modify those instances' attributes, in order for SaveEdits() to work?

Perhaps what I'm trying to accomplish isn't possible.  If that's the case, I have some alternate workarounds that I can explore.  It would be cool, though, if I could use the existing API to accomplish this task.

Thanks!
Brooks
0 Kudos
7 Replies
JenniferNery
Esri Regular Contributor
Sure you will need to create a FeatureLayer that represent the RelatedTable and if you want to add an entry to this table, you will need to add Graphics with attributes matching the fields of this table. If you set AutoSave to false, you need to explicitly call SaveEdits().
0 Kudos
BrooksShannon
New Contributor
Thanks, Jennifer!  Using a FeatureLayer to represent my related table ends up working well.  I can create, update, and delete related records as you'd expect, with no issues.  Thanks for confirming that my initial idea was possible, and not totally off-base and unreasonable. 🙂

Regards,
Brooks
0 Kudos
CaseyBentz
Occasional Contributor II
I know that this was a long time ago, but I am wanting to do the exact same thing you are talking about here.  I am using a query to return a single point feature that has a 1:M relationship with a related table.  I have been successful in bringing back the related record, but do not know where to go from here.  If you could post some code, that would be great.
0 Kudos
BrooksShannon
New Contributor
Casey,

I'm unfortunately unable to, at the moment, dig up my code that accomplishes this (as I'm currently applying ArcGIS 10 SP1 - my machine is pretty pegged).  I figured I'd describe what I did, however, and see if I might be able to point you in the direction I took.

Basically, my application has two FeatureLayers.  One represents the features on the left hand side of the 1:M relationship, while the second represents the features or records on the right hand side. 

Let's say we have one feature from the left hand side of the relationship.  I'll use the QueryTask.ExecuteRelationshipQueryAsync() method to obtain all of the features/records that are related to it.  When I receive the response, I do this:

1) Clear the contents of my "related records" FeatureLayer.
2) Tell the "related records" FeatureLayer that its set of OIDs are the ones that I obtained from the result of QueryTask.ExecuteRelationshipQueryAsync().  (There is a property on the FeatureLayer, OIDs I think, that you can use to do this.)
3) Call FeatureLayer.Update(), forcing it to go retrieve the records.

At this point, I can perform edits on the "related records" feature layer, just as I would any other feature layer. 

The key here is that my "related records" feature layer acts like a scratch workspace, and is only ever composed of those records related to a given, single "working feature" from the left hand side of the relationship.

Let me know if you have any more questions; I'm certainly happy to explain in further depth how I did this (much less try to explain more clearly, if I didn't do a good job at that.  I think I still need a bit more coffee...)

Thanks!
Brooks
0 Kudos
CaseyBentz
Occasional Contributor II
Brooks,

Thanks for the info.  It really helped me understand how to set it up.  I took your concepts and combined pieces from several of the samples and I can now delete a related record and edit one.  I now need to figure out how to create one.  I am guessing that when I get no related record back from my query, I will have to pop up a form or something for the user to input a new one.  Does that sound right?
0 Kudos
BrooksShannon
New Contributor
Casey,

That does sound like an effective approach.  As long as the user has a way of providing the data required to create a new record, you'd be set.

My app displays the related records in a DataGrid, and if users want to create new related records, they simply click an "Add" button.  Then, the fun starts:

1)  I create a new Graphic instance.
2)  I manually set one of its attribute values, the foreign key, to the primary key of the record it's related to. (This is how you wire up the relationship back to the record that exists on the "left hand side" of your 1:M relationship.)
3)  I add the graphic instance to my "related records" FeatureLayer. Voila!  You can start adding and modifying the graphic's attributes just like preexisting records.

As the user supplies attribute values for the new record, just make sure the attribute names match those in the database itself.  Say your FeatureLayer has an attribute called "NAME".  Your new graphic instance won't have a "NAME" attribute yet, but you can add one, and when you save your FeatureLayer's edits, that new value will flow back to the database.  However, if you tried to add an attribute called something else, like "SNAZZY_NEW_ATTRIBUTE" to your new graphic instance - an attribute that doesn't exist in your database - you'll run into problems.  When you save the FeatureLayer's edits, the call will bomb, since there isn't a "SNAZZY_NEW_ATTRIBUTE" field in your database.

I hope this helps!

Have a good one,
Brooks
0 Kudos
Jitendrudulacaraju
New Contributor
Can you share a sample code on this?


Casey,

That does sound like an effective approach.  As long as the user has a way of providing the data required to create a new record, you'd be set.

My app displays the related records in a DataGrid, and if users want to create new related records, they simply click an "Add" button.  Then, the fun starts:

1)  I create a new Graphic instance.
2)  I manually set one of its attribute values, the foreign key, to the primary key of the record it's related to. (This is how you wire up the relationship back to the record that exists on the "left hand side" of your 1:M relationship.)
3)  I add the graphic instance to my "related records" FeatureLayer. Voila!  You can start adding and modifying the graphic's attributes just like preexisting records.

As the user supplies attribute values for the new record, just make sure the attribute names match those in the database itself.  Say your FeatureLayer has an attribute called "NAME".  Your new graphic instance won't have a "NAME" attribute yet, but you can add one, and when you save your FeatureLayer's edits, that new value will flow back to the database.  However, if you tried to add an attribute called something else, like "SNAZZY_NEW_ATTRIBUTE" to your new graphic instance - an attribute that doesn't exist in your database - you'll run into problems.  When you save the FeatureLayer's edits, the call will bomb, since there isn't a "SNAZZY_NEW_ATTRIBUTE" field in your database.

I hope this helps!

Have a good one,
Brooks
0 Kudos