托管对象上下文保存未保存到持久存储中
在准备我的应用程序更新时,我发现了一个奇怪的问题,到目前为止一直有点令人头疼。
我有一种简单的方法,可以获取托管对象,更新一个属性,然后将更改保存到持久存储中。奇怪的是,有时,它似乎并没有真正将堆栈一直保存到数据库,但它会返回 true 来表示成功保存,并且不会填充 NSError 对象。
我已经通过打开 SQL 日志记录验证了这一点 - 在一次调用中,我没有看到 UPDATE 语句,但在具有相同输入的同一方法的第二次调用中,我看到了 UPDATE。
真的很奇怪。我肯定做错了什么,但我一整天都盯着这个,但我无法弄清楚。
这是有问题的方法:
+ (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 {
...
//log fetch error
}
}
这是我在调用此方法时看到的两组日志。
我已经验证,在这两种情况下,它们都是从主线程调用的。
它们是一个接一个地运行的。
运行#1(无 SQL 更新):
2011-04-30 17:25:27.107 应用程序[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 来自 ZTIPTEMPLATE t0 其中 t0.ZProductID = ?
2011-04-30 17:25:27.110 App [15024:707] CoreData:注释:sql 连接获取时间:0.0028s
2011-04-30 17:25:27.111 App [15024:707] CoreData:注释:总获取执行时间:1 行 0.0043 秒。
2011-04-30 17:25:27.112 应用程序[15024:707] 将“Steve's Creations”标记为已购买:1
运行 #2(SQL 更新):
2011-04-30 17:27:37.536应用程序[15024:707] CoreData:sql:选择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 来自 ZTripTEMPLATE t0,其中 t0.ZProductID = ?
2011-04-30 17:27:37.537 App [15024:707] CoreData:注释:sql 连接获取时间:0.0015s
2011-04-30 17:27:37.538 App [15024:707] CoreData:注释:总获取执行时间:1 行 0.0024 秒。
2011-04-30 17:27:37.539 应用程序[15024:707] 将“史蒂夫的创作”标记为已购买:1
2011-04-30 17:27:37.540 应用程序[15024:707] CoreData:sql:开始独家
2011-04 -30 17:27:37.542 应用程序[15024:707] CoreData:sql:更新ZTIPTEMPLATE SET ZPURCHASED =?,Z_OPT =? Z_PK = 哪里?和 Z_OPT = ?
2011-04-30 17:27:37.544 App[15024:707] CoreData: sql: COMMIT
有什么建议我可以开始寻找我的问题吗?
在这两种情况下,提取都有效,因此 MOC 至少能够与商店对话。
In prepping my app for an update, I've found a weird issue that's so far been a bit of a head-scratcher.
I have a simple method that fetches a managed object, updates one attribute and then saves the change to the persistent store. The weird thing is that some of the time, it doesn't seem to actually save all the way down the stack to the DB and yet it returns true for a successful save and doesn't populate the NSError object.
I've verified this by turning on SQL logging - in one call, I see no UPDATE statement but in a second call of the same method with the same inputs, I see the UPDATE.
Really weird. I must be doing something wrong but I've been staring at this all day and I can't figure it out.
Here's the method in question:
+ (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 {
...
//log fetch error
}
}
Here are the two sets of logs I see when calling this method.
I've verified that in both cases they're being called from the main thread.
They're being run one after the other.
Run #1 (no SQL update):
2011-04-30 17:25:27.107 App[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: sql connection fetch time: 0.0028s
2011-04-30 17:25:27.111 App[15024:707] CoreData: annotation: total fetch execution time: 0.0043s for 1 rows.
2011-04-30 17:25:27.112 App[15024:707] Marking 'Steve's Creations' as Purchased: 1
Run #2 (SQL update):
2011-04-30 17:27:37.536 App[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:27:37.537 App[15024:707] CoreData: annotation: sql connection fetch time: 0.0015s
2011-04-30 17:27:37.538 App[15024:707] CoreData: annotation: total fetch execution time: 0.0024s for 1 rows.
2011-04-30 17:27:37.539 App[15024:707] Marking 'Steve's Creations' as Purchased: 1
2011-04-30 17:27:37.540 App[15024:707] CoreData: sql: BEGIN EXCLUSIVE
2011-04-30 17:27:37.542 App[15024:707] CoreData: sql: UPDATE ZTRIPTEMPLATE SET ZPURCHASED = ?, Z_OPT = ? WHERE Z_PK = ? AND Z_OPT = ?
2011-04-30 17:27:37.544 App[15024:707] CoreData: sql: COMMIT
Any suggestions where I might start looking for my problem?
In both cases, the fetch works so it seems the MOC is at least capable of talking to the store.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在查看代码时,我唯一可以建议的错误是您以某种方式将不同的上下文传递给该方法。如果是这样,并且您不合并上下文,那么如果您保存在一个上下文中但从另一个上下文中进行检查,则不会显示更改。
我建议记录整个模板对象、上下文和上下文的更新对象。你需要确保你正在与你认为的对象交谈。
In looking at the code, the only thing I could suggest as an error would be that you are somehow passing different context to the method. If so, and you don't merge the contexts, then changes won't show if you save in one but examine from another.
I would suggest logging the entire template object, the context and the context's updatedObjects. You need to make sure you are talking to the objects you think you are.