2011-06-03 82 views
3

我在10.6中编写了一个简单的Cocoa应用程序。在程序运行时(程序定期保存到数据存储区),我停电,并且我的程序使用的sqlite文件已经以某种方式损坏。停电后的sqlite存储中的核心数据损坏

我创建一个标准的方式被管理对象上下文:

managedObjectContext = [[NSManagedObjectContext alloc] init]; 
[managedObjectContext setPersistentStoreCoordinator: coordinator]; 

,通常一切都很好,但是这一次,读取对象时:

NSLog(@"%@",dir.files); 

我得到:

2011-06-03 11:33:38.079 Backup Check[1927:3c03] Relationship fault for 
(<NSRelationshipDescription: 0x100562230>), name files, isOptional 1, 
isTransient 0, entity Directory, renamingIdentifier files, validation 
predicates ( 
), warnings (
), versionHashModifier (null), destination entity File, inverseRelationship 
directory, minCount 0, maxCount 0 on 0x10058bbc0 

我在命令行尝试了sqlite3工具,很多东西都可以正确读取,但是对于som Ë表读我得到了一堆表项,然后:

SQL error: database disk image is malformed 

我猜测,在保存时正好发生了停电。我有几个问题: 1)我该如何检测/恢复?现在我没有收到任何我创建对象上下文时可以看到的错误。此外,许多表格都没有错误,只有在深入研究子表格时,我才会发现这种关系错误。我无法检查null,因为一个对象正在被返回 - 它只是不是NSSet。这是某种关系故障对象。 2)我如何采取措施预防未来的腐败?在创建托管对象上下文时是否有一种简单的方法来检查一致性,如果检测到损坏,我可以回滚到旧版本?在应用程序支持目录中,我只看到一个文件,这是损坏的数据库。

回答

3

没有任何API工具可以修复损坏的SQL存储。它简直是如此罕见的事件,没有多少意义。我在过去5年以上看到了一个损坏的Core Data SQL商店。

从NSLog获取的打印输出不会指出错误。使用“故障”一词并不意味着在这种情况下的错误,而是表明它是故障对象。故障是代表关系中管理对象的轻量级“虚影”对象故障用于维护对象图的完整性,而无需加载与每个对象关联的所有数据。获取会默认返回关系错误,因此在关系中查看它们是正常的,并不表示错误。

SQL错误指示数据库的模式已损坏。没有自动化的方法来解决这个问题。您只需wh出您的疯狂的低级SQL技能并将数据库重新拼接在一起即可。这样做很不值得。 (首先,你必须解开苹果公司没有记录的模式)。

最后,没有办法保护任何基于文件的持久性存储器停电。如果写入硬件出现故障,即使是大铁杆也会被丢弃。 (这就是服务器UPS系统如此重要的原因。)不管你做什么,在某个时刻你都有写硬件或发送数据的硬件,如果硬件出现故障,那么在软件中你就无能为力了。添加更多写入制作两份或更多份,只是增加了更多的中断点。

这些类型的腐败非常罕见,所以我不打算试图对付它们。但是,如果你偏执狂,一个简单的部分解决方案是定期将存储文件复制到备份中,以便至少可以恢复到以前的版本,而不必从头开始。

+0

感谢您的信息。我不在乎修理这个特别的商店,而是防止未来发生。有一件事我仍然想知道 - 我有一个名为Directory的管理对象,带有一个类成员“files”。我的理解是,当我到NSLog的类成员,它会被提取。但在这里,当我真正尝试将消息传递给NSSet“.files”时,它会使程序崩溃。我怎么可以在这里放一些代码来检查并看看ghost对象是否实际上不指向任何东西,因此我可以重建coredata存储? – Ryan 2011-06-03 19:55:07

+0

不,一个关系中的对象将被默认取为故障。这是为了防止级联加载大量的对象。当您访问故障表示的对象的属性时,故障只会转换为管理对象(行话中的“故障”)。看到“关系错误”简单并不是错误。将故障看作“占位符对象”。 – TechZen 2011-06-03 20:17:21