如何使用通用关系构建Core Data中的实体?

Jos*_*low 11 cocoa core-data objective-c ios

假设您需要使用可与多个其他类型的实体关联的实体构建应用程序.例如,您有一个Picture实体,可以与Meal实体,Person实体,Boardroom实体,Furniture实体等相关联.我可以想到许多不同的方法来解决这个问题,但是 - 也许是因为我是Core Data的新手 - 我对其中任何一个都不满意.

想到的最明显的方法是简单地创建Picture和支持相关图片的每个实体之间的关系,但这看起来很草率,因为图片将有多个"空指针".

另一种可能性是创造一种超级性 - 可想象 - 或者某种东西.支持相关图片的每个实体都是Pictureable的子实体,而Picture本身将与Pictureable一对一.我发现这种方法令人不安,因为它不能在项目的上下文中多次使用(因为Core Data不支持多重继承)以及Core Data似乎为任何给定的根实体创建一个表的方式 - 假设一个SQLite支持 - 让我更倾向于在一个共同的超级大国的保护下对一大堆不同的子实体进行分组(我意识到沿着这些方向思考可能会导致过早的优化,所以如果我是一个狡猾的人,请告诉我).

第三种方法是为Picture创建一个由"type"和"UID"组成的复合键.假设我的数据模型中的每个实体都有一个UID,我可以使用此密钥从Picture实例派生关联的托管对象,反之亦然.这种方法让我感到担心,因为听起来它总体来说可能会变慢 ; 它对我来说也不够原生.

第四种方法 - 我倾向于我正在研究的应用程序 - 正在创建图片和X的子实体(其中X是餐,人,会议室等)并创建一个 - - 在这两个子实体之间.虽然这种方法似乎是所有邪恶中较小的一种,但对于我未经训练的眼睛来说它似乎仍然是深奥的,所以我想知道是否有更好的方法.

编辑1:在最后一段,我的意思是说我倾向于创造子实体只是对图片,不是两个图片和X.

Cal*_*leb 5

我认为这个主题的最佳变体是(不一定按顺序):

  1. 对与 Meal、Person、Boardroom 等相关联的图片使用单独的实体。这些实体可能都具有相同的属性,实际上它们可能都使用相同的类来实现。这并没有什么错,它使得在每种实体和存储其图片的实体之间建立双向关系变得简单。

  2. 使图片成为每个实体类型的属性,而不是单独的实体。如果您将实际图片数据存储在数据库中,这在效率方面并不是一个很好的计划,但如果您将图像存储为单独的文件并将该文件的路径存储在属性中,那就没问题了。如果图像或记录数量很少,即使您将图像数据存储在数据库中,也可能不是真正的问题。

  3. 对所有图片使用单个实体,但省略与关联实体的反向关系。有一个有用的 SO 问题考虑了这一点,并且接受的答案链接到文档中更有用的单向关系部分。如果您不需要图片->所有者关系,这可以很好地解决您的问题,但您应该在走这条路之前了解可能的风险。

  4. 正如您在列出的第一个选项中所述,为每种可能的所有者赋予图片实体单独的关系。如果您需要能够将所有图片作为一个组访问,并且您需要从图片返回到其所有者的关系,并且如果可能的所有者实体的数量相对较少,这可能是您的最佳选择,即使它有空属性似乎很草率。

正如您所注意到的,当您对实体使用继承时,所有子实体最终会聚集在一张大表中。因此,您的第四个选项(为每种图片使用子实体)在本质上与您的第一个选项类似。

关于这个问题,我更倾向于使用实体继承来为与每种类型的所有者实体关联的图片创建子实体。图片实体将只存储与任何图片关联的数据。每个子实体,如 MealPicture 和 PersonPicture,都会为其自己的特定类型的所有者添加关系。这样,您将获得双向 Meal<->MealPicture 和 Person<->PersonPicture 关系,并且由于每个子实体都继承了所有常见的图片内容,因此您可以避免困扰您的 DRY 违规。简而言之,您可以获得上述选项 1 和 3 的大部分最佳部分。在幕后,Core Data 像上面的选项 4 一样管理图片,但在使用中,每个图片子实体只公开一个关系。

  • +1 图片问题是一个相当普遍的问题。我认为具有多个自定义图像实体的 (1) 解决方案都由同一个 NSManagedObject 子类实现是最好的方法。对于那些在强大的面向对象学校中训练的用户来说,这有点乏味并且感觉“错误”,但实体实际上并不是类,它们在操作中的行为不同,因此它确实是最好的选择。 (3认同)