Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm returning a featureset from an SOE.

To create the FeatureSet, I'm first creating a Recordset, inserting features into it, and then serializing it as json using SOESupport. The client then deserializes it as a featureset.

The resulting featureset has different OIDs. Is there a way to preserve the OIDs of the features I'm inserting into the recordset?

When I perform a query using the REST API, the featureset returned has the original objectID's.

IMapServer3.QueryData might do this, but I don't see a way to pass it an array of OIDs as I can with IFeatureClass.GetFeatures.

share|improve this question
up vote 1 down vote accepted

I think your problem is you are creating a new featureset and inserting into it. ESRI will always create a new OID since there is there Index, this is there primary key; the only place this does not happen is if your in a SDE using a GlobalID that you use for replication.

I have never seen a OID be a constant between layers. Your easiest solution which I have used is to create a LinkID or such that you can control; then as you move your data around you control the state of that ID. It is more of a pain; but in the long run I have seen it be my best/only solution.

share|improve this answer
Thanks D.E. this looks like the way I'll go. Esri sure needs to review the role objectIDs plays in primary key/ foreign key mgmt. – Kirk Kuykendall Jun 7 '11 at 21:13

I've also have this requirement. I solved this by using GlobalIDs as the Primary keys of my tables and feature classes.

share|improve this answer
Thanks George. I'd like to avoid adding any new columns to the table. I also like using IFeatureClass.GetFeatures, which I don't think has anything similar that works with GlobalIDS. – Kirk Kuykendall Jun 7 '11 at 21:10

If my memory serves me right, a Recordset uses an InMemoryWorkspace as its internal structure to manage its behavior/storage. This, like with any other GeoDatabase type, means that it manages its own ObjectIDs and you won't have access to modify them.

Nevertheless, there is one operation that will preserve objects ids... copy and paste. Without more details, I can't tell you if you can use it in your context, but the applicable interface is IGeoDBDataTransfer. Theoretically this should just work because the Recordset is using the InMemoryWorkspace, but you have to try it :)

About the other portion of your comment regarding IMapServer3.QueryData3, it does have access to a QueryFilter (and thus access to a WhereClause). This means you can do a whereclause like "Objectid in (1,3,4,5,blah,....)". In fact, many internal GeoDatabase cursors do this.

share|improve this answer
Thanks Ragi. Would I need to worry about some maximum string length for the whereclause? I might have a lot of objectIDs. – Kirk Kuykendall Jun 7 '11 at 20:15
Yes you do. The limit is datasource-specific. If you batch read them 50 at a time, it may be slower than usual, but it will keep you in the safe side. – Ragi Yaser Burhum Jun 7 '11 at 21:04

There is a workaround for this behavior which does not require you to introduce new additional identifiers and makes the recordset preserve OIDs:

Suppose you have an ITable, an enumeration of IRows from this table and want to turn them into a recordset.

  1. Clone the table's Fields via IClone.Clone
  2. Cast this field collection to IFieldsEdit.
  3. Search for the oid field (i.e. search for a field with type esriFieldTypeOID), save its name (most likely will be "OBJECTID") and modify its type to esriFieldTypeInteger through IFieldEdit. The behavior which changes identifiers will subsequently not be in effect because the field will no longer be treated as a special case.
  4. Create the RecordSetClass and initialize it with IRecordSetInit.CreateTable method, passing in the modified fields.
  5. Fill the recordset with data by calling IRecordSetInit.Insert which will create an insert cursor. Use the cursor to insert rows from the table. You will probably pass in rows you previously retrieved from a search cursor on the table.
  6. Now you have the objectids preserved but the field type information will be incorrect when you serialize the recordset in JSON, which may or may not be an issue for you. You can fix the type in the newly created recordset as follows:

    a. Access IRecordSet.Fields, cast to IFieldsEdit.

    b. Find the altered field (by name you saved previously, e.g. "OBJECTID") and modify the type (via IFieldEdit) back to esriFieldTypeOID. Because the recordset is already filled with data, the type will be correct and OBJECTIDs preserved.

It may seem like a lot of steps, but is pretty straightforward and can be easily factored out to a library function. It does rely on implementation details within RecordSet, but I would not expect those to change.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.