Ios 核心数据模型设计-更改“;“生活”;对象也会更改保存的对象

Ios 核心数据模型设计-更改“;“生活”;对象也会更改保存的对象,ios,iphone,core-data,data-modeling,Ios,Iphone,Core Data,Data Modeling,我正在做我的第一个核心数据项目(在iPhone上),我真的很喜欢它。核心数据是很酷的东西 然而,我遇到了一个设计难题,我不知道如何解决,尽管我认为这是一个相当普遍的情况。它涉及数据模型 为了清楚起见,我将使用一个虚构的足球游戏应用程序作为示例来说明我的问题。比如说,NSMO有一个名为Downs and Plays的游戏。播放与Downs使用的模板类似的功能。用户创建播放(例如,盗录、按钮挂钩、倾斜路线、扫描等)并填充各种属性。戏剧与唐斯有着千丝万缕的联系。对于每个向下,用户决定使用哪个播放。当向

我正在做我的第一个核心数据项目(在iPhone上),我真的很喜欢它。核心数据是很酷的东西

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

为了清楚起见,我将使用一个虚构的足球游戏应用程序作为示例来说明我的问题。比如说,NSMO有一个名为Downs and Plays的游戏。播放与Downs使用的模板类似的功能。用户创建播放(例如,盗录、按钮挂钩、倾斜路线、扫描等)并填充各种属性。戏剧与唐斯有着千丝万缕的联系。对于每个向下,用户决定使用哪个播放。当向下执行时,它使用播放作为其模板。每次向下运行后,都会将其存储在历史记录中。这个程序会记住所有的下摆

到目前为止,一切顺利。这一切都很好

我的问题是,当用户想要更改一个剧本的细节时会发生什么。假设它最初涉及到向左传递,但用户现在希望它是向右传递。然而,做出这样的改变不仅会影响该剧未来的所有演出,还会改变历史上保存的剧本的细节。事实上,由于播放模板已被更改,Downs的记录被“污染”

我一直在寻找几种可能的方法来解决这个问题,但我想,美国的天才们比我更了解如何处理这个问题。不过,我提出的潜在解决方案是:

  • 剧本的“版本控制”。对播放模板的每次更改实际上都会创建一个新的、具有相同名称的单独播放对象(据用户所知)。然而,在引擎盖下,这实际上是一个不同的游戏。AFAICT,这是可行的,但似乎可能会导致播放对象的大量增加,特别是如果用户在同一个播放的多个版本之间来回切换(每次用户切换时都会创建一个又一个对象)。是的,应用程序可以检查预先存在的相同播放,但是。。。看起来就像一团糟

  • 保存时,记录他们使用的播放的详细信息,但不作为播放对象。这看起来很可笑,因为游戏对象就是用来保存这些细节的

  • 认识到播放对象实际上实现了两个功能:一个是向下播放的模板,另一个是记录使用的模板。这两个函数与Down的关系不同。第一个(模板)具有对多关系。但第二条(记录)是一对一的关系。这意味着创建第二个对象,类似于“Play Template”,它将保留与Downs的多对多关系。游戏对象将被重新配置为与Downs具有一对一的关系。Down将使用Play Template对象来执行,但使用新类型的Play对象来存储所使用的模板。正是这种从一对多关系到一对一关系的转变代表了问题的症结所在

  • 即使把这个问题写出来也能让我更清楚。我认为解决方案3就是答案。然而,如果有人有更好的想法,甚至只是确认我走上了正确的道路,那将是很有帮助的。(记住,我并不是真的在做一场足球比赛,只是用一个大家都能理解的比喻更快/更容易。)

    我认为你的#3是最清晰、最明智的选择。它很好地涵盖了(隐喻性)应用程序的预期用途


    不久前,我在一个跟踪测试的应用程序中遇到了类似的情况;这些测试包含多个问题,可以在多个日期进行更改和重新管理。拥有一个测试模板以及单独的测试对象,使整个模型更容易处理。

    我认为您需要重新开始设计

    (1) 为什么要使用PlayEntity作为DownEntity的模板?实体实际上是(隐藏的)类,因此类定义本身就是每个实例的“模板”

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

    在您的示例中,播放和播放模式完全不同

    停机是按时间顺序排列的事件。在任何特定的游戏中,只有一个特定的失败。这意味着足球史上每场比赛的每一次失利都是独一无二的。因此,下跌数据模型实体主要感兴趣的是建模下跌与其他下跌和整个游戏的时间关系

    相比之下,戏剧是一种空间事件。游戏不是唯一的,通常在一个游戏中以及在一个游戏之间重复。一个游戏实体应该关注球员、球和场地之间的空间关系

    你会得到这样的结果:

    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;
    }
    
    请注意,两个实体都不复制另一个实体的属性中包含的信息。他们也没有共享继承权,因为他们没有对游戏的相同方面进行建模。向下模拟时间序列,播放模拟空间序列。这需要他们两人都完整地描述各自的遭遇


    您可以通过首先创建所需的任何标准化实体来构建数据库。如果您有一个新的剧本,您将创建一个新的剧本实体,并根据需要填充它。每次发生故障时,您都会创建一个故障实体,并与现有或新创建的故障实体建立关系

    也许我对我目前设计的描述不够详细,而且有很多不足之处