Core Data中的线程安全唯一实体实例

时间:2010-02-02 05:07:16

标签: cocoa core-data macos

我有一个Message实体,它有一个messageID属性。我想确保只有一个具有给定messageID的Message实体的实例。在SQL中,我只是在messageID列中添加一个唯一约束,但我不知道如何使用Core Data执行此操作。我不相信它可以在数据模型本身中完成,那么你如何去做呢?

我最初的想法是使用验证方法对NSManagedObject的ID上下文进行提取,看看它是否找到了除自身之外的任何内容,如果是,则验证失败。我怀疑这会奏效 - 但我担心这样的表现。我花了很多精力来最小化整个导入例程所需的获取请求,并通过对每个新的消息实体执行获取来验证它似乎有点过分。我可以获得我需要的所有预先存在的对象,并在我执行导入和连接所有内容的实际工作之前,仅使用两个获取查询来识别我需要插入到商店中的所有新对象。除了这两个更新或插入之外,这将添加一个提取 - 这似乎消除了我首先通过预处理导入数据所带来的任何性能优势!

这是一个问题的主要原因是导入器可以(可能)在多个线程上同时运行多个批次,并且可能包括一些重叠/重复数据,这些数据最终只需要在存储中生成一个对象而不是重复条目。有没有合理的方法来做到这一点,并且我要求的核心数据是否有意义?

4 个答案:

答案 0 :(得分:3)

保证唯一性的唯一方法是进行提取。幸运的是,您只需执行-countForFetchRequest:error:并检查它是否为零。这是目前保证唯一性的最便宜的方式。

您可以在验证中完成此操作,或者在处理数据的循环中运行它。就个人而言,我会在创建NSManagedObject之上这样做,这样当记录已经存在时你没有不必要的分配。

答案 1 :(得分:1)

我不认为有一种方法可以轻松保证属性是唯一的,而无需自行完成很多的工作。当然,您可以使用CFUUIDCreate创建全局唯一的UUID,即使在多线程环境中也应该是唯一的。但...

保证所有托管对象的objectID(类型NSManagedObjectID)在持久性存储协调器中是唯一的。由于您可以向协调器添加任意多个持久存储,因此此保证基本上保证objectID是全局唯一的。为什么不使用objectID作为messageID?当然,您不能在分配objectID之后更改它(并且在保存包含插入对象的上下文之前不会分配它;在此之前它将是一个临时但仍然是唯一的ID。)< / p>

答案 2 :(得分:1)

所以你有一个NSManagedContext用于每个线程,由同一个持久存储支持,这是正确的吗?在保存NSManagedContext之前,您需要确保messageID是唯一的,即您没有更新现有行,并且它不在其他上下文中,是否正确?

鉴于该模型(如果我误解了,请纠正我),我认为如果有一个对象来管理对持久性存储的访问,你会更好。这样,所有线程都会更新一个上下文,您可以使用Marcus的-countForFetchRequest:error:建议在那里进行验证。当然,这会给这次行动带来瓶颈。

答案 3 :(得分:0)

只是为了加上我的2美分:我认为无论如何迟早会出现不一致的地方,减轻它们的唯一方法似乎是在应用程序级别上使用相当复杂的代码。

所以在我的情况下,我决定允许重复的值为&#34; unique&#34; 字段。

然而,我添加了代码,以便稍后检测到这些问题(例如,当应该返回1个对象的提取返回多于1时)并在它们发生时修复它们(通常通过删除)。

它是&#34;继续前进,犯错误,稍后为你解决问题&#34; -strategy。

当然,这不是理想的,但是有效的方法可以解决这个问题,imho。