核心数据模型devise – 更改“活动”对象也会更改保存的对象

我正在开发我的第一个Core Data项目(在iPhone上),我非常喜欢它。 核心数据是很酷的东西。

然而,我却遇到了一个devise难题,我不知道如何解决,尽pipe我想这是一个相当普遍的情况。 它涉及数据模型。

为了清楚起见,我将以一个虚构的足球游戏应用为例来说明我的问题。 说有NSMO的叫唐斯和戏剧。 戏剧function像唐斯使用的模板。 用户创build播放(例如,Bootleg,button挂钩,倾斜路线,扫描等)并填写各种属性。 戏剧与唐斯有多对多的关系。 对于每个Down,用户决定使用哪个Play。 当执行下来时,它使用播放作为它的模板。 每次运行结束后,它都存储在历史logging中。 该scheme记得所有的唐斯玩过。

到现在为止还挺好。 这一切工作正常。

我所关心的问题是当用户想要改变Play的细节时会发生什么。 我们假设它最初涉及左边的传球,但是用户现在想要传球到右边。 但是,进行这种改变不仅会影响Play的所有未来执行, 还会改变历史中存储的Plays的细节 。 Downs的logging实际上被“污染”,因为Play模板已被更改。

我一直在围绕着这种情况进行几个可能的解决scheme,但是我认为SO的天才比我更了解如何处理这个问题。 不过,我提出的潜在问题是:

  1. 剧本的“版本化”。 对Play模板的每个更改实际上都会创build一个具有相同名称的新的单独的Play对象(就用户而言)。 然而,在引擎盖下面,这实际上是一个不同的游戏。 这可能会起作用,AFAICT,但似乎可能会导致Play对象的一个​​狂放的扩散,特别是。 如果用户不断地在同一个Play的几个版本之间来回切换(每次用户切换时在对象之后创build对象)。 是的,应用程序可以检查预先存在的,相同的Plays,但是…看起来像一团糟。

  2. 让Downs在保存后logging他们使用的Play的细节,但不能将其作为Play对象。 这看起来很荒谬,因为Play对象只是在那里保存那些细节。

  3. 认识到Play对象实际上实现了两个function:一个是Down的模板,另一个是logging使用的模板。 这两个函数与Down有不同的关系。 第一个(模板)有一个多对多的关系。 但是第二个(唱片)有一个一对一的关系。 这意味着要创build第二个对象,就像“Play-Template”,它可以保留与Downs的多对多关系。 玩对象将被重新configuration为与唐斯有一个一对一的关系。 Down将使用Play-Template对象来执行,但使用新的Play对象来存储使用的模板。 这是从一对多关系到代表问题关键的一对一关系的转变。

即使写出这个问题也帮助我更清楚。 我认为像解决scheme3是答案。 但是,如果有人有更好的主意,甚至只是确认我走在正确的轨道上,那将是有益的。 (请记住,我并不是真的在制作一个足球比赛,而是使用每个人都能理解的比喻更快更简单。)

我认为你需要重新开始你的devise。

(1)为什么使用PlayEntity作为DownEntity的模板? 实体是(真正的)类,所以类定义本身就是每个实例的“模板”。

(2)pipe理对象应表示真实对象的数据模型或真实的信息关系。 因此,您需要认真思考自己想要build模的真实对象或信息。 一个好的开始就是问自己如何用笔和纸logging这些信息。

在你的例子中,Plays和Downs模型完全不同的东西。

Down是按时排列的事件。 在任何特定的游戏中只有一个特定的Down。 这意味着足球历史上每场比赛的每一场比赛都是独一无二的。 因此,Down数据模型实体将主要关心对Down的关系进行build模,以便及时处理其他的崩溃和整个游戏。

相比之下,播放是一个空间事件。 戏剧不是独一无二的,经常在游戏中和游戏中重复。 游戏实体应该关注玩家,球和场之间的空间关系。

你最终会得到这样的结果:

DownEntity{ game; half; quarter; turnover; gameClockTime; yardLine; penalties; play --(required,Cascade)->PlayEntity.down previousDown --(optional, nullify)-->Down.nextDown; nextDown --(optional, nullify)-->Down.previousDown } PlayEntity { playName; //whatever other detail you want to model down --(optional,nullify)-->>DownEnity.play; } 

请注意,两个实体都不会复制另一个实体的属性中保存的信息。 他们也不共享inheritance,因为他们没有模拟游戏的相同方面。 Down模拟一个时间序列,Play模拟一个空间序列。 它要求他们两个完整地描述每个发生了什么事。

你可以通过首先创build你想要的任何标准化的PlayEntities来build立你的数据库。 如果你有一个新的游戏,你会创build一个新的PlayEntity,并根据需要填充它。 每当你有一个失败,你会创build一个DownEntity并创build一个关系到现​​有或新创build的PlayEntity。

我会把你的#3作为最明智,最明智的select。 它涵盖了您的(隐喻)应用程序的预期用法。

一段时间以来,我遇到了一个类似的情况,那就是跟踪testing人员的应用程序。 testing包含多个问题,可以在多个date更改和重新pipe理。 拥有testing模板以及单独的testing对象,使得整个模型更容易处理。