代码之家  ›  专栏  ›  技术社区  ›  Sean

核心数据中的线程安全唯一实体实例

  •  4
  • Sean  · 技术社区  · 16 年前

    我有一个具有messageid属性的消息实体。我想确保只有一个具有给定message i d的消息实体实例。在SQL中,我只需要为messageid列添加一个惟一的约束,但我不知道如何使用核心数据来实现这一点。我不相信它可以在数据模型本身中完成,那么你该怎么做呢?

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

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

    4 回复  |  直到 12 年前
        1
  •  3
  •   Marcus S. Zarra    16 年前

    唯一能保证唯一性的方法就是做一个获取。幸运的是你可以做一个 -countForFetchRequest:error: 检查它是否为零。这是目前最便宜的保证独特性的方法。

    您可能可以在验证中完成这一点,或者在处理数据的循环中运行它。就我个人而言,我会在 NSManagedObject 这样,当记录已经存在时,您就没有不必要的分配了。

        2
  •  1
  •   Barry Wark    16 年前

    我不认为有一种方法可以轻易地保证一个属性是唯一的,而不用做 很多 你自己的工作。当然,你可以用 CFUUIDCreate 创建一个全局唯一的uuid,即使在多线程环境中也是唯一的。但是…

    这个 objectID (类型) NSManagedObjectID )在所有托管对象中,保证在持久存储协调器中是唯一的。由于您可以向协调器任意添加许多持久性存储,因此此保证基本上保证 客体 S是全球独一无二的。为什么不使用 对象ID 作为您的messageid?当然,你不能改变 客体 一旦分配了它(在保存包含插入对象的上下文之前,它不会被分配;在此之前,它将是一个临时但仍然唯一的ID)。

        3
  •  1
  •   Don    16 年前

    因此,每个线程都有一个nsmanagedContext,由同一个持久存储支持,对吗?在保存nsmanagedContext之前,您要确保messageID是唯一的,也就是说,您没有更新现有的行,并且它不在其他上下文中,对吗?

    考虑到这个模型(如果我误解了的话,请纠正我),我认为您最好有一个对象来管理对持久存储的访问。这样,所有线程都将更新一个上下文,您可以在其中使用Marcus的 -countForFetchRequest:error: 建议。当然,这会给这个操作带来瓶颈。

        4
  •  0
  •   scrrr    12 年前

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

    所以在我的例子中,我决定允许重复的值 “独特” 领域。

    但是,我添加了稍后检测这些问题的代码(例如,当应该返回1个对象的FETCH返回超过1个对象时),并在出现问题时(通常通过删除)对其进行修复。

    这是一个 “去吧,犯个错误,以后我给你修” -策略。

    当然,这不是理想的,而是攻击这个问题的有效方法。