In preparing my application for the update, I discovered a strange problem, which until now has been a bit of a puzzle.
I have a simple method that retrieves a managed entity, updates a single attribute, and then saves the changes to persistent storage. The strange thing is that at some point it doesnβt seem to actually save all the way down the stack in the database, and yet it returns true to save successfully and does not populate the NSError object.
I checked this by turning on SQL logging - in one call I do not see the UPDATE statement, but in the second call of the same method with the same inputs, I see UPDATE.
Really strange. I must be doing something wrong, but I keep looking at it all day, and I can't figure it out.
The method in question here is:
+ (void)markTemplateAsPurchasedWithProductID:(NSString *)productID inContext:(NSManagedObjectContext *)context {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"TripTemplate" inManagedObjectContext:context];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"(productID = %@)", productID]];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
if ([fetchedObjects count] > 0) {
TripTemplate *template = [fetchedObjects lastObject];
template.purchased = [NSNumber numberWithBool:YES];
NSLog(@"Marking '%@' as Purchased: %@", template.name, template.purchased);
NSError *saveError;
if (![context save:&saveError])
NSLog(@"Error Saving Purchased For Template: %@ - %@", template, saveError);
} else {
...
}
}
Here are two sets of logs that I see when calling this method.
I checked that in both cases they are called from the main thread.
They run one after another.
Run # 1 (without updating SQL):
2011-04-30 17: 25: 27.107 Appendix [15024: 707] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZLASTAPPSTOREPRICE, t0.ZPURCHASED, t0.ZISFREE, t0.ZNAME, t0.ZPRODUCTID , t0.ZSERVERID, t0.ZTRIPDESCRIPTION, t0.ZAUTHORDESCRIPTION, t0.ZAUTHORURL, t0.ZCREATEDAT, t0.ZAUTHORNAME FROM ZTRIPTEMPLATE t0 WHERE t0.ZPRODUCTID =?
2011-04-30 17: 25: 27.110 App [15024: 707] CoreData: annotation: time to connect sql: 0.0028s
2011-04-30 17: 25: 27.111 Appendix [15024: 707] CoreData: annotation: total sampling time: 0.0043s for 1 row.
2011-04-30 17: 25: 27.112 [15024: 707] " " : 1
β2 ( SQL):
2011-04-30 17: 27: 37.536 [15024: 707] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZLASTAPPSTOREPRICE, t0.ZPURCHASED, t0.ZISFREE, t0.ZNAME, t0.ZPRODUCTID, t0.ZSERVERID, t0.ZTRIPDESCRIPTION, t0.ZAUTHORDESCRIPTION, t0.ZAUTHORURL, t0.ZCREATEDAT, t0.ZAUTHORNAME FROM ZTRIPTEMPLATE t0 t0.ZPRODUCTID =?
2011-04-30 17: 27: 37.537 [15024: 707] CoreData: : sql: 0.0015s
2011-04-30 17: 27: 37.538 [15024: 707] CoreData: : : 0.0024s 1 .
2011-04-30 17: 27: 37.539 [15024: 707] " " : 1
2011-04-30 17: 27: 37.540 [15024: 707] CoreData: sql: BEGIN EXCLUSIVE
2011-04-30 17: 27: 37.542 [15024: 707] CoreData: sql: UPDATE ZTRIPTEMPLATE SET ZPURCHASED =?, Z_OPT =? WHERE Z_PK =? Z_OPT =?
2011-04-30 17: 27: 37.544 App [15024: 707] CoreData: sql: COMMIT
, ?
, , MOC, , .