Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data batch update

I am trying to run a batch update on selected objects in my Core Data database (SQLite) but my request returns 0 items updated (no error message). My entity "SDRDFileObject" has a property selected (Bool in my model), which I want to set to NO for all objects satisfying my fetch predicate:

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(isLeaf == 1) AND (direction ==  1) AND (myLR == 1)"];

 NSEntityDescription *entity = [NSEntityDescription entityForName:@"SDRDFileObject"
                                     inManagedObjectContext:self.context];

NSBatchUpdateRequest *reqL = [[NSBatchUpdateRequest alloc] initWithEntity:entity];
reqL.predicate = predicate;
reqL.resultType = NSUpdatedObjectIDsResultType;

reqL.includesSubentities = YES;
reqL.propertiesToUpdate = @{
                            @"selected" : @(NO)
                            };

NSError *error;
NSBatchUpdateResult *resL = (NSBatchUpdateResult *)[self.context executeRequest:reqL error:&error];

This returns 0 items updated. However, if I use the same settings to make an estimate of the number of affected objects I get 1764 (which is correct):

 NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
[request setResultType:NSUpdatedObjectIDsResultType];
[request setReturnsDistinctResults:YES];
[request setPropertiesToFetch:@[@"selected"]];


NSError *err;
NSUInteger count = [self.context countForFetchRequest:request error:&err];

NSLog(@"Estimated fetch request count : %li",count);

Does anyone have suggestions as to what I am doing wrong here? Should I write the keyPath any different? I appreciate suggestions and help.

Update I followed the suggestion for debugging the SQL commands and it seems to fail, although I am not sure how to interpret the error message. The first SQL calls are for the countForFetchRequest which suceeds and then comes the batch request that fails.

CoreData: sql: SELECT COUNT( DISTINCT t0.Z_PK) FROM ZSDRDFILEOBJECT t0     WHERE ( t0.ZISLEAF = ? AND  t0.ZDIRECTION = ? AND  t0.ZMYLR = ?) 
CoreData: annotation: total count request execution time: 0.0005s for count of 0.
2017-11-15 16:56:09.560121+0100 TEST[69278:3739361] Estimated fetch  request count : 1764
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: SELECT 0, t0.Z_PK FROM ZSDRDFILEOBJECT t0 WHERE (  t0.ZISLEAF = ? AND  t0.ZDIRECTION = ? AND  t0.ZMYLR = ?) 
CoreData: annotation: sql connection fetch time: 0.0000s
CoreData: annotation: total fetch execution time: 0.0001s for 0 rows.
CoreData: sql: UPDATE OR FAIL ZSDRDFILEOBJECT SET ZSELECTED = ?, Z_OPT = (Z_OPT + 1) WHERE (ZISLEAF = ? AND ZDIRECTION = ? AND ZMYLR = ?) 
CoreData: sql: pragma auto_vacuum
CoreData: annotation: sql execution time: 0.0000s
CoreData: sql: pragma auto_vacuum=2
CoreData: annotation: sql execution time: 0.0003s
CoreData: sql: COMMIT
like image 767
Trond Kristiansen Avatar asked Jul 19 '26 17:07

Trond Kristiansen


1 Answers

The first SQL count returns 0, but the context returns 1764. So it looks like the objects which meet your criteria have not yet been saved to the SQLite store. The batch update works directly on the SQLite store, so it cannot update the unsaved items.

So either save the context first, or update the objects directly in the context - which should be quick, since they are already registered with the context and do not need to be fetched.

like image 64
pbasdf Avatar answered Jul 21 '26 14:07

pbasdf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!