使用核心数据更新对象会插入一条新记录

Posted

技术标签:

【中文标题】使用核心数据更新对象会插入一条新记录【英文标题】:Updating object with core data inserts a new record 【发布时间】:2013-12-18 03:53:23 【问题描述】:

我正在尝试更新核心数据中的一条记录,但它实际上是在插入一条新记录。以下代码用于解锁我的游戏的下一个级别。

- (void)unlockNextLevel

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *levelEntity = [NSEntityDescription entityForName:@"Level"
                                                   inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:levelEntity];

    int nextLevelPosition = [self.position intValue] + 1;

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                              [NSString stringWithFormat:@"position == %i",
                               nextLevelPosition]];
    [fetchRequest setPredicate:predicate];

    NSError *error;

    NSArray *result = [[self managedObjectContext] executeFetchRequest:fetchRequest
                                                                          error:&error];

    if (error) 
        NSLog(@"%@", error.description);
    

    if (result.count > 0) 
        Level *nextLevel = result[0];

        nextLevel.locked = [NSNumber numberWithBool:NO];

        [self saveContext];
    

这里我通过它的位置的值来获取一个对象,它应该是唯一的(按照惯例),然后改变它的“锁定”属性。我期待更新它,但核心数据正在插入一条新记录...

我正在更新的对象与它所属的世界有关。所以一个世界有很多关卡,一个关卡只有一个世界。

我认为值得一提的是,插入到 SQLite 中的记录没有引用 World(世界的 id 为空)。

希望你能帮助我。

【问题讨论】:

【参考方案1】:

下一行是创建新“级别”实体的位置。

NSEntityDescription *levelEntity = [NSEntityDescription entityForName:@"Level"
                                               inManagedObjectContext:[self managedObjectContext]];

我认为您可以改用以下代码初始化获取请求:

NSFetchRequest *req = [[NSFetchRequest alloc] initWithEntityName:@"Level"];

并删除以下行:

 [fetchRequest setEntity:levelEntity];

【讨论】:

【参考方案2】:

在核心数据实体 swift 4 中更新记录

    let appDelegate = UIApplication.shared.delegate as! AppDelegate

    let context = appDelegate.persistentContainer.viewContext

    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")

    request.predicate = NSPredicate(format: "age = %@ AND username = %@",self.dictData[0].value(forKey: "age") as! CVarArg,self.dictData[0].value(forKey: "username") as! CVarArg)

    do 

        let result = try context.fetch(request)

        let objUpdate = result[0] as! NSManagedObject

        let strUN = txtFldUserName.text!
        let strPassword = txtFldPassword.text!
        let strAge = txtFldAge.text!

        // put all entity field
        objUpdate.setValue(strUN, forKey: "username")
        objUpdate.setValue(strPassword, forKey: "password")
        objUpdate.setValue(strAge, forKey: "age")

        print("update success!")
        try context.save()

     catch 
        print("Failed")
    

希望对您有所帮助!

【讨论】:

【参考方案3】:

试试这个方法。首先获取具有某些唯一属性值(如 articleID)的所需实体。如果您将实体设为 nil,则创建新的实体实例或更新它。

Entity * entityInstance = nil;
 entityInstance = [self fetchEntityForID:entityInstanceID inContext:context];

 if (entityInstance == nil) 

 entityInstance = [NSEntityDescription insertNewObjectForEntityForName:@"Entity" inManagedObjectContext:context];


-(Entity *)fetchEntityForID:(NSNumber *) articleID inContext:(NSManagedObjectContext *) writeContext

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"articleID == %@",articleID];
    [fetchRequest setPredicate:predicate];

    NSArray *fetchedArray = [writeContext executeFetchRequest:fetchRequest error:nil];
    if ([fetchedArray count] > 0) 
        return [fetchedArray objectAtIndex:0];
    
    return nil;

希望对你有帮助:)

【讨论】:

以上是关于使用核心数据更新对象会插入一条新记录的主要内容,如果未能解决你的问题,请参考以下文章

如数据不存在就插入,存在就更新

Oracle整合Mybatis实现list数据插入时,存在就更新,不存在就插入以及随机抽取一条记录

将MYSQL某一数据库中的多条记录批量插入到另一MYSQL数据库时,记录不存在则插入,存在则更新

使用游标更新Temp表中的记录

如何在插入第一条记录并将其添加到对象数组后“保存”表?

MySQL数据库基础(操作数据表中的记录)(持续更新中)