1

我很难理解数据模型。让我首先展示如果我只需要拥有内存中的对象,我将如何声明该类。

@interface PlayerState {

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

}

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

@end;

我只有两个不同组的相同类型的东西。因此,当我在 Core Data 中对其进行建模时,我认为我只有从 PlayerState 到 SavedDie 的两个对多关系。

当我尝试定义反向关系时,问题就来了。首先,我真的不明白为什么一对多关系必须有逆向关系。我知道如果您不定义逆,您有责任保持一致性,但即使我这样做,我似乎也有问题。

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

4

2 回答 2

3

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

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

于 2010-08-22T01:56:12.117 回答
2

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

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

创建 Core Data 是为了自动管理所有这些,它使用实体图来做到这一点。实体不是类。相反,它们是主要对象之间关系的抽象表示。实体图不会让您让一个实体与另一个实体有两个关系,因为不可能跟踪实时数据对象的哪些实例相互关联。

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

(1) 使用实体继承:您创建一个Die实体并使用您希望它拥有的所有属性对其进行设置。然后创建两个子实体:SavedDieImmediateDie. 然后你设置关系:

PlayerState.savedDie<-->SavedDie.playerState 
PlayerState.immediateDie<-->>ImmediateDie.playerState

(2) 使用获取的关系:在这种情况下,你有一个Die实体和一个关系:

PlayerState.Die<-->>Die.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只需删除一个链接关系并创建另一个链接关系,就可以在关系周围移动实例。由于Die.player指向ToDie它的点将接受任何一个PlayerToSavedDiePlayerToImmediateDie在该关系中。

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

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

Core Data 使关系管理变得容易了一百倍,但仍然需要一些工作。

于 2010-08-22T23:32:05.747 回答