核心数据:DELETE WHERE

Posted

技术标签:

【中文标题】核心数据:DELETE WHERE【英文标题】:Core Data: DELETE WHERE 【发布时间】:2011-11-16 20:45:01 【问题描述】:

我知道如何使用 NSPredicate 来执行类似 SQL SELECT 的操作。如何执行DELETE WHERE 之类的操作?我必须为每个获取的对象调用[NSManagedObjectContext deleteObject] 吗?谢谢

NSError *error;

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:TASK_ENTITY inManagedObjectContext:managedObjectContext]];

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"label LIKE  %@", label];
[request setPredicate:predicate];

NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];

[managedObjectContext deleteObject:[array objectAtIndex:0]];

【问题讨论】:

我添加了使用可以批量删除对象的新 API (ios 9.0+) 的答案:***.com/a/43388746/468724 【参考方案1】:

我相信循环返回的数组并调用[NSManagedObjectContext deleteObject:] 是“正确”/惯用的方法。这可能看起来效率低下,但请记住,fetch 命令实际上并不获取对象的数据,deleteObject: 方法只是将对象标记为删除,当您发送[NSManagedObjectContext save:] 时会应用该对象。不知道 Core Data 的内部结构,我无法告诉您它是否与 DELETE WHERE 查询一样高效(可能 Core Data 在内存中具有从获取中获取的索引主键,并使用这些主键),但根据我对 Core Data 进行分析的经验应用它并不比保存新的或更新的对象慢很多。

【讨论】:

【参考方案2】:

您可以在iOS 9.0+macOS 10.11+tvOS 9.0+watchOS 2.0+ 上使用NSBatchDeleteRequest

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label LIKE  %@", label];
NSFetchRequest *fetchRequest = [TaskEntity fetchRequest];
[fetchRequest setPredicate:predicate];
// Create batch delete request
NSBatchDeleteRequest *deleteReq = [[NSBatchDeleteRequest alloc] initWithFetchRequest:fetchRequest];
NSError *error = nil;
NSBatchDeleteResult *deletedResult = [appDelegate.persistentContainer.viewContext executeRequest:deleteReq error:&error];
if (error) 
  NSLog(@"Unable to delete the data");

else 
  NSLog(@"%@ deleted", deleteReq.result);


Swift 代码(来自上面的链接)

let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Employee")
fetch.predicate = NSPredicate(format: "terminationDate < %@", NSDate())
let request = NSBatchDeleteRequest(fetchRequest: fetch)

do 
    let result = try moc.execute(request)
 catch 
    fatalError("Failed to execute request: \(error)")


注意:

我在下面找到了关于executemoc 的评论

在不影响托管对象上下文内容的情况下将请求传递给存储的方法。

这意味着moc 中任何未保存的数据都不会受到影响。即,如果您创建/更新了符合删除请求标准的实体,并且没有在 moc 上调用 save,那么该对象将不会被删除。

【讨论】:

【参考方案3】:

除了使用NSArray 删除方法外,我还没有找到其他方法。 (如果有我想知道的) 如果您真的不想存储数组,则可以将调用嵌套在一行上。但是,如果您这样做,请验证在发生错误时 Fetch 的返回值是什么。

ma​​keObjectsPerformSelector: 向数组中的每个对象发送由给定选择器标识的消息,从第一个对象开始,然后通过数组一直到最后一个对象。 - (void)makeObjectsPerformSelector:(SEL)aSelector

或者有一个块可以更快。

【讨论】:

【参考方案4】:

我刚刚试了一下,成功了:

NSError *error = nil;
NSFetchRequest* fetchrequest = [NSFetchRequest fetchRequestWithEntityName:@"EntityName"];
[request setPredicate:[NSPredicate predicateWithFormat:@"attribute == %@", variable]];
NSArray *deleteArray = [context executeFetchRequest:fetchrequest error:&error];

if (deleteArray != nil)

    for (NSManagedObject* object in deleteArray)
    
        [context deleteObject:object];

        //Reload/refresh table or whatever view..
    

    [context save:&error];

【讨论】:

【参考方案5】:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:TASK_ENTITY inManagedObjectContext:managedObjectContext];

[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"label LIKE%@", label.text]];

NSError* error = nil;

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

if(![results count]==0)

   [managedObjectContext deleteObject:[results objectAtIndex:0]];

if (![managedObjectContext save:&error]) 
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);

【讨论】:

以上是关于核心数据:DELETE WHERE的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 3 删除核心数据托管对象

从 asp.net 核心应用程序发出 DELETE 请求时出现 405 错误

EF 核心 6 选择空值,尽管 where 子句要求不为空

人事工资信息管理系统(核心代码实现)

人事工资信息管理系统(核心代码实现)

无法获取具有 SQL 等条件的核心数据