Realm-java: Field "activityModelId" cannot be a primary key, it already contains duplicate values

Created on 22 Feb 2016  路  3Comments  路  Source: realm/realm-java

Hi,

i'm using Realm (v0.87.2) on my project (which is in production).
Now I have to update a RealmObject by adding a PrimaryKey and I'm stuck with this error:
_Field "activityModelId" cannot be a primary key, it already contains duplicate values_
This is fired by my migration code:

// Migrating from version 1 to 2
if (oldVersion == 1) {
    RealmObjectSchema activityModelSchema = schema.get("ActivityModel");
    activityModelSchema.addField("activityModelId", String.class, FieldAttribute.PRIMARY_KEY);
    activityModelSchema.transform(new RealmObjectSchema.Function() {
        @Override
        public void apply(DynamicRealmObject obj) {
            String accountId = obj.getObject("account").getString("accountId");
            String modelAbspath = obj.getString("modelAbspath");
            // Generate primary key
           String newUid = modelAbspath + accountId;
           BPLogger.v(TAG, "New filler activity model ID " + newUid);
           obj.set("activityModelId", newUid);
           }
        });
    oldVersion++;
}

I'm testing my new app version with an existing database.
Is there a way to update RealmObject and delete duplicate values generated by migration?

Any help is appreciated, thank you in advance.
Frasprite

T-Duplicate

Most helpful comment

I just needed to accomplish something similar. In my scenario, I had a primary key and actually needed to change it without losing data :fearful: .

The reason you're running into troubles is because your old table already contains data, and each change in the schema happens live, not all at the end. So once you say it's a primary key, it checks to ensure uniqueness immediately.

Here's what I had to do.

  1. Remove the old primary key (you might not need this step)
  2. Create the new field, do not mark it as a primary key yet.
  3. Set the new field to a unique value for each instance using transform
  4. Add an index to the new field.
  5. Make the new field a primary key.

The example code is Kotlin because that's what I use in production, but it converts to Java pretty directly.

table.removePrimaryKey()
                        .addField("_realmId", Long::class.java)
                        .transform { oldObject ->
                            oldObject.setLong("_realmId", oldObject.getLong("id"))
                        }
                        .addIndex("_realmId")
                        .addPrimaryKey("_realmId")

All 3 comments

I just needed to accomplish something similar. In my scenario, I had a primary key and actually needed to change it without losing data :fearful: .

The reason you're running into troubles is because your old table already contains data, and each change in the schema happens live, not all at the end. So once you say it's a primary key, it checks to ensure uniqueness immediately.

Here's what I had to do.

  1. Remove the old primary key (you might not need this step)
  2. Create the new field, do not mark it as a primary key yet.
  3. Set the new field to a unique value for each instance using transform
  4. Add an index to the new field.
  5. Make the new field a primary key.

The example code is Kotlin because that's what I use in production, but it converts to Java pretty directly.

table.removePrimaryKey()
                        .addField("_realmId", Long::class.java)
                        .transform { oldObject ->
                            oldObject.setLong("_realmId", oldObject.getLong("id"))
                        }
                        .addIndex("_realmId")
                        .addPrimaryKey("_realmId")

Thank you for your answer @bclymer , I will give it a try!

@bclymer Nice workaround! We have an issue to track this problem, see #2167

@Frasprite I am closing this issue now for easy issue tracking. Feel free to reopen it if needed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Jeff11 picture Jeff11  路  54Comments

cornflakes picture cornflakes  路  51Comments

DinuIoan picture DinuIoan  路  60Comments

loosemoose picture loosemoose  路  64Comments

bfichter picture bfichter  路  80Comments