Allow updating of primary keys
See original GitHub issueGoal
There should be a method for updating the primary key of an object after it has been created. Previously one could update it using e.g. object.setId(newId)
, but starting with Realm 2.0.0 this throws an exception to keep it in line with the Realm API in other languages. See the dicussion in Pull Request #3418. The workflow of my app is similiar to the following:
- User creates a new object in the database while offline
- This object gets a temporary (negative) id, as the app does not yet know what final id the server will assign to the object
- User/app syncs the database when online again
- The server receives the new object and assigns a final id to it
- The app receives the final id from the server and updates the objects id to the final one (this is currently not directly supported by Realm)
Expected Results
I personally see 2 options going forward with this:
-
Reallow changing primary key fields: this would basically put it in the same state as previously with the following code to update an objects primary key:
TestObject object = realm.where(TestObject.class).equalTo("mId", oldId).findFirst(); object.setId(newId);
-
Add dedicated method for changing primary keys: this probably makes more sense if you want to align it more with the Realm API in other languages:
realm.updatePrimaryKey(TestObject.class, oldId, newId);
Actual Results
Currently only a rather ugly and not very performant workaround does the job, basically bypassing the check by making an in-memory copy of the object:
private static <E extends RealmObject> void updatePrimaryKey(Realm realm, Class<E> type, long oldId, long newId) {
E object = realm.where(type).equalTo("mId", oldId).findFirst();
E copy = realm.copyFromRealm(object);
copy.setId(newId);
realm.insertOrUpdate(copy);
object.deleteFromRealm();
}
I’m really looking forward to seeing this fixed in a future update (though I absolutely acknowledge that you have lots of other issues to attend to 😉)
Version of Realm and tooling
Realm version(s): >2.0.0 Android Studio version: all Which Android version and device: all
References
realm-cocoa: https://github.com/realm/realm-cocoa/issues/4194
Issue Analytics
- State:
- Created 7 years ago
- Reactions:15
- Comments:34 (13 by maintainers)
Any update on this issue? This is still a huge pain point for me. I love Realm and it is making lots of progress, yet this limitation has continued to annoy me. Currently I just copy the fields and then delete the old object, but unfortunately this triggers the change listener with a deletion and not with the new updated fields. 😢
I would be glad if you could tell me what would I need to do to remove this limitation? What parts of the code would need to be changed. Would you be interested in a pull request (that e.g. ties this limitation to the
syncEnabled
variable)? Thanks in advance!@stk1m1 I understand the purpose and value of primary keys, but still I have to update my primary key once (and only once). Call it bad design, but it’s _required_ in my case. In the current library I have to do workarounds, which is ugly to say the least.
Let me reiterate this: I totally agree that primary keys normally shouldn’t be updated, there’s no doubt about that. But in my case there’s no other way. Being offline, a client can’t tell the next id that’s usable in the server database. As such, it has to assign a temporary id to the object, of which it is sure that it won’t clash with any server objects already synced with the client database (i.e. negative ids in my case). One could theoretically try to generate unique ids on the device, but there’s currently no reliable way to do this. Generating temporary ids is such the best a client can do. In order to keep everything consistent though, the client has to update the primary key after the server has assigned the final id though. That is unavoidable and currently unsupported by Realm, which is why I created this issue. I hope I could shed some more light on the use case.