领域-无法使用现有的主键值创建对象 [英] Realm - Can't create object with existing primary key value

查看:63
本文介绍了领域-无法使用现有的主键值创建对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象有很多狗的人.应用程序具有单独的页面,其中仅显示狗,而其他页面则显示人的狗

I have a object Person with many dogs. App has separate page where it shows just dogs and other page where it shows person's dogs

我的模型如下

class Person: Object {
    dynamic var id = 0
    let dogs= List<Dog>()

    override static func primaryKey() -> String? {
        return "id"
    }
}

class Dog: Object {
    dynamic var id = 0
    dynamic var name = ""

    override static func primaryKey() -> String? {
        return "id"
    }
}

我的人存储在Realm中.人有详细信息页面,我们在这里获取并展示他的狗.如果狗已经存在,我会更新该狗的最新信息,并将其添加到人员的狗列表中,否则创建新的狗,保存并将其添加到人员列表中.这适用于coredata.

I have persons stored in Realm. Person has detail page where we fetch and show his dogs. If dog already exist, I update latest info for that dog and add it to person's dog list else create new dog, save it and add it to persons list. This works in coredata.

// Fetch and parse dogs
if let person = realm.objects(Person.self).filter("id =\(personID)").first {
    for (_, dict): (String, JSON) in response {
        // Create dog using the dict info,my custom init method
        if let dog = Dog(dict: dict) {
            try! realm.write {
                // save it to realm
                realm.create(Dog, value:dog, update: true)
                // append dog to person
                person.dogs.append(dog)
            }
        }
    }
    try! realm.write {
        // save person
        realm.create(Person.self, value: person, update: true)
    }
}

在试图用狗更新人时,领域抛出异常 无法使用现有的主键值创建对象

On trying to update person with his dogs,realm throws exception Can't create object with existing primary key value

推荐答案

这里的问题是,即使您正在创建一个全新的Realm Dog对象,您实际上并没有将该对象持久化到数据库中,并且因此,当您呼叫append时,您正在尝试添加第二个副本.

The problem here is that even though you're creating a completely new Realm Dog object, you're not actually persisting that one to the database, and so when you call append, you're trying to add a second copy.

调用realm.create(Dog, value:dog, update: true)时,如果数据库中已存在具有该ID的对象,则只需使用创建的dog实例中的值更新该现有对象,但该dog实例是仍然是独立副本;它不是数据库中的Dog对象.您可以通过检查dog.realm是否等于nil来确认这一点.

When you call realm.create(Dog, value:dog, update: true), if an object with that ID already exists in the database, you're simply updating that existing object in with the values in the dog instance you created, but that dog instance is still an independent copy; it's not the Dog object in the database. You can confirm this by checking if dog.realm is equal to nil or not.

因此,当您调用person.dogs.append(dog)时,由于dog尚未存在于数据库中,因此Realm尝试创建一个全新的数据库条目,但由于已经存在具有该ID的狗而失败.

So when you call person.dogs.append(dog), because dog is not already in the database, Realm tries to create a whole new database entry, but fails because there is already a dog with that ID.

如果要将该dog对象附加到person,则必须查询Realm以检索引用数据库中条目的正确的dog对象.幸运的是,这对于由主键支持的Realm对象确实很容易,因为您可以使用Realm.object(ofType:forPrimaryKey:)方法:

If you want to append that dog object to a person, it'll be necessary to query Realm to retrieve a proper dog object that's referencing the entry in the database. Thankfully this is really easy with Realm objects backed by primary keys since you can use the Realm.object(ofType:forPrimaryKey:) method:

if let person = realm.object(ofType: Person.self, forPrimaryKey: "id") {
    for (_, dict): (String, JSON) in response {
        //Create dog using the dict info,my custom init method
        if let dog = Dog(dict: dict)
        {
            try! realm.write {
                //save it to realm
                realm.create(Dog, value: dog, update: true)
                //get the dog reference from the database
                let realmDog = realm.object(ofType: Dog.self, forPrimaryKey: "id")
                //append dog to person
                person.dogs.append(realmDog)
            }
        }
    }
    try! realm.write {
        //save person
        realm.create(person .self, value: collection, update: true)
    }
}

这篇关于领域-无法使用现有的主键值创建对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆