领域 - 无法使用现有主键值创建对象
Realm - Can't create object with existing primary key value
我有一个对象 Person 和很多狗。应用程序有单独的页面,它只显示狗和其他页面,它显示人的狗
我的模型如下
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 中存储了人物。 Person 有详细信息页面,我们可以在其中获取并展示他的狗。如果狗已经存在,我会更新该狗的最新信息并将其添加到人的狗列表中,否则创建新狗,将其保存并将其添加到人列表中。这适用于核心数据。
// 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)
}
}
在尝试用他的狗更新 person 时,realm 抛出异常
无法使用现有主键值创建对象
这里的问题是,即使您正在创建一个全新的 Realm Dog
对象,您实际上并没有将该对象持久保存到数据库中,因此当您调用 append
时,您正在尝试添加第二个副本。
当您调用 realm.create(Dog.self, value:dog, update: true)
时,如果数据库中已存在具有该 ID 的对象,您只需使用您创建的 dog
实例中的值更新该现有对象,但是dog
实例仍然是一个独立的副本;它不是数据库中的 Dog
对象。您可以通过检查 dog.realm
是否等于 nil
来确认这一点。
所以当你调用 person.dogs.append(dog)
时,因为 dog
不在数据库中,Realm 尝试创建一个全新的数据库条目,但失败了,因为已经有一只狗具有该 ID。
如果您想将 dog
对象附加到 person
,则需要查询 Realm 以检索引用数据库中条目的正确 dog
对象.值得庆幸的是,这对于由主键支持的 Realm 对象来说真的很容易,因为您可以使用 Realm.object(ofType:forPrimaryKey:)
方法:
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.self, 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)
}
}
最新API解决方案:
使用add(_:update:)
.
try realm.write {
realm.add(objects, update: Realm.UpdatePolicy.modified)
// OR
realm.add(object, update: .modified)
}
Realm.UpdatePolicy 枚举:
error (default)
modified //Overwrite only properties in the existing object which are different from the new values.
all //Overwrite all properties in the existing object with the new values, even if they have not changed
NB: Works on Realm Swift 3.16.1
我有一个对象 Person 和很多狗。应用程序有单独的页面,它只显示狗和其他页面,它显示人的狗
我的模型如下
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 中存储了人物。 Person 有详细信息页面,我们可以在其中获取并展示他的狗。如果狗已经存在,我会更新该狗的最新信息并将其添加到人的狗列表中,否则创建新狗,将其保存并将其添加到人列表中。这适用于核心数据。
// 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)
}
}
在尝试用他的狗更新 person 时,realm 抛出异常 无法使用现有主键值创建对象
这里的问题是,即使您正在创建一个全新的 Realm Dog
对象,您实际上并没有将该对象持久保存到数据库中,因此当您调用 append
时,您正在尝试添加第二个副本。
当您调用 realm.create(Dog.self, value:dog, update: true)
时,如果数据库中已存在具有该 ID 的对象,您只需使用您创建的 dog
实例中的值更新该现有对象,但是dog
实例仍然是一个独立的副本;它不是数据库中的 Dog
对象。您可以通过检查 dog.realm
是否等于 nil
来确认这一点。
所以当你调用 person.dogs.append(dog)
时,因为 dog
不在数据库中,Realm 尝试创建一个全新的数据库条目,但失败了,因为已经有一只狗具有该 ID。
如果您想将 dog
对象附加到 person
,则需要查询 Realm 以检索引用数据库中条目的正确 dog
对象.值得庆幸的是,这对于由主键支持的 Realm 对象来说真的很容易,因为您可以使用 Realm.object(ofType:forPrimaryKey:)
方法:
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.self, 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)
}
}
最新API解决方案:
使用add(_:update:)
.
try realm.write {
realm.add(objects, update: Realm.UpdatePolicy.modified)
// OR
realm.add(object, update: .modified)
}
Realm.UpdatePolicy 枚举:
error (default)
modified //Overwrite only properties in the existing object which are different from the new values.
all //Overwrite all properties in the existing object with the new values, even if they have not changed
NB: Works on Realm Swift 3.16.1