Core data 如何实现从一个实体到同一实体的两对多关系的效果?

Core data 如何实现从一个实体到同一实体的两对多关系的效果?,core-data,entity-relationship,inverse,Core Data,Entity Relationship,Inverse,我很难将头脑集中在数据模型上。首先让我展示一下,如果必须有内存中的对象,我将如何声明该类 @interface PlayerState { NSSet /* of SavedDie */ *savedDice; NSSet /* of SavedDie */ *immediateRolls; } @property (nonatomic, retain) NSSet *savedDice; @property (nonatomic, retain) NSSet *immediate

我很难将头脑集中在数据模型上。首先让我展示一下,如果必须有内存中的对象,我将如何声明该类

@interface PlayerState {

  NSSet /* of SavedDie */ *savedDice;
  NSSet /* of SavedDie */ *immediateRolls;

}

@property (nonatomic, retain) NSSet *savedDice;
@property (nonatomic, retain) NSSet *immediateRolls;

@end;
我只是有两组不同类型的东西。所以,当我在核心数据中建模时,我认为从PlayerState到SavedDie只有两对多的关系

当我试图定义一个反向关系时,问题就来了。首先,我真的不明白为什么很多关系都有相反的结果。我知道如果你不定义一个反比,你有责任保持一致性,但即使我这样做,我似乎也有问题


无论如何,我可以在SavedDie上定义一个名为owner的对一关系,尽管我不需要在代码中访问它。我可以将savedDice的反向关系定义为所有者。然后,如果我试图将immediateRolls的反向关系定义为owner,它将其取消设置为savedDice的反向关系。当然,我不能将owner的反向关系设置为savedDice和immediateRolls。

您不能完全按照此处的操作。如果我理解正确,您希望一个骰子有一个单一的所有者关系,但playerState有两个不同的已保存和立即的关系,每个都与所有者反向链接。CoreData不允许这样做


你可能应该重新考虑一下你的模型;也许可以向SavedDie对象添加一个标志,指示它是“已保存”卷还是“立即”卷。然后根据该标志添加动态属性以获取刚刚保存或立即的骰子。一对一的关系。当然,如果它们更合适的话,还有其他方法可以做到这一点

你不可能完成你在这里想要做的事情。如果我理解正确,您希望一个骰子有一个单一的所有者关系,但playerState有两个不同的已保存和立即的关系,每个都与所有者反向链接。CoreData不允许这样做


你可能应该重新考虑一下你的模型;也许可以向SavedDie对象添加一个标志,指示它是“已保存”卷还是“立即”卷。然后根据该标志添加动态属性以获取刚刚保存或立即的骰子。一对一的关系。当然,如果它们更合适的话,还有其他方法可以做到这一点

您不能直接在核心数据中执行此操作,因为与上面的示例不同,核心数据还必须维护关系图

为了理解这一点,假设您使用上面的示例代码手动设置关系。现在假设您有一个SavedDie类,它保存在PlayerState的savedDice和immediateRolls中。如果希望每个SavedDie实例都引用PlayerState,那么创建指向所属PlayerState的指针将很容易,但是您如何知道它存储在哪个PlayerState属性中呢。更重要的是,如何强制执行它,使同一个SavedDie对象不会同时出现在两个属性中,或者出现在两个或多个单独的PlayerState对象中

创建核心数据是为了自动管理所有这些,它使用实体图来实现这一点。实体不是类。相反,它们主要是对象之间关系的抽象表示。实体图不允许一个实体与另一个实体有两个关系,因为不可能跟踪活动数据对象的哪些实例彼此关联

有两种方法可以解决你的问题

1使用实体继承:创建一个模具实体,并将其设置为您希望它具有的所有属性。然后创建两个子实体:SavedDie和immediate。然后设置关系:

PlayerState.savedDie<-->SavedDie.playerState 
PlayerState.immediateDie<-->>ImmediateDie.playerState
。。。但是您有一个Die属性,它使每个实例都被保存或立即保存。然后创建两个获取关系,其谓词分别查找标志的不同状态

3使用链接实体:在这种技术中,使用中间实体将两个主要实体以多种关系连接在一起,如下所示:

PlayerState{
    //...some attributes
    savedDice<-->>PlayerToSavedDie.playerState
    immediateDice<-->>PlayerToImmediateDie.playerState
}

ToDie{
    die<-->SaveDie.player
}
PlayerToSavedDie:ToDie{ //...subentity of ToDie
    //... no attributes
    playerState<<-->PlayerState.savedDice
}

PlayerToImmediateDie:ToDie{ //...subentity of ToDie
    //... no attributes
    playerState<<-->PlayerState.savedDice
}

Die{
    player<-->ToDie.die
}
这样,只需删除一个链接关系并创建另一个链接关系,就可以在关系周围移动模具实例。由于Die.player指向ToDie,因此它将在该关系中接受playertosavedie或playertoimmedie

使用哪种技术取决于数据模型的需要。如果一个关系中的逻辑骰子对象从未跳转到另一个,请使用1。如果保存的数据或即时数据是逻辑模具对象本身的重要属性,请使用2。如果逻辑模具对象需要在关系之间移动,并且保存的或即时的数据不是逻辑模具对象的一部分,则使用3

所有这一切似乎都需要做很多工作,但你必须记住一件重要的事情:关系和属性一样重要!如果模型的关系不能反映模型模拟的真实世界对象、事件或条件,则模型将无法工作 艾茨。你应该花些时间思考和管理人际关系


核心数据使关系管理变得容易了一百倍,但仍然需要一些工作

您不能直接在核心数据中执行此操作,因为与上面的示例不同,核心数据还必须维护关系图

为了理解这一点,假设您使用上面的示例代码手动设置关系。现在假设您有一个SavedDie类,它保存在PlayerState的savedDice和immediateRolls中。如果希望每个SavedDie实例都引用PlayerState,那么创建指向所属PlayerState的指针将很容易,但是您如何知道它存储在哪个PlayerState属性中呢。更重要的是,如何强制执行它,使同一个SavedDie对象不会同时出现在两个属性中,或者出现在两个或多个单独的PlayerState对象中

创建核心数据是为了自动管理所有这些,它使用实体图来实现这一点。实体不是类。相反,它们主要是对象之间关系的抽象表示。实体图不允许一个实体与另一个实体有两个关系,因为不可能跟踪活动数据对象的哪些实例彼此关联

有两种方法可以解决你的问题

1使用实体继承:创建一个模具实体,并将其设置为您希望它具有的所有属性。然后创建两个子实体:SavedDie和immediate。然后设置关系:

PlayerState.savedDie<-->SavedDie.playerState 
PlayerState.immediateDie<-->>ImmediateDie.playerState
。。。但是您有一个Die属性,它使每个实例都被保存或立即保存。然后创建两个获取关系,其谓词分别查找标志的不同状态

3使用链接实体:在这种技术中,使用中间实体将两个主要实体以多种关系连接在一起,如下所示:

PlayerState{
    //...some attributes
    savedDice<-->>PlayerToSavedDie.playerState
    immediateDice<-->>PlayerToImmediateDie.playerState
}

ToDie{
    die<-->SaveDie.player
}
PlayerToSavedDie:ToDie{ //...subentity of ToDie
    //... no attributes
    playerState<<-->PlayerState.savedDice
}

PlayerToImmediateDie:ToDie{ //...subentity of ToDie
    //... no attributes
    playerState<<-->PlayerState.savedDice
}

Die{
    player<-->ToDie.die
}
这样,只需删除一个链接关系并创建另一个链接关系,就可以在关系周围移动模具实例。由于Die.player指向ToDie,因此它将在该关系中接受playertosavedie或playertoimmedie

使用哪种技术取决于数据模型的需要。如果一个关系中的逻辑骰子对象从未跳转到另一个,请使用1。如果保存的数据或即时数据是逻辑模具对象本身的重要属性,请使用2。如果逻辑模具对象需要在关系之间移动,并且保存的或即时的数据不是逻辑模具对象的一部分,则使用3

所有这一切似乎都需要做很多工作,但你必须记住一件重要的事情:关系和属性一样重要!如果模型的关系不反映模型模拟的真实世界对象、事件或条件,则模型将无法工作。你应该花些时间思考和管理人际关系

核心数据使关系管理变得容易了一百倍,但仍然需要一些工作