Как мне добиться эффекта двух-многих отношений к одному и тому же объекту от одного объекта? - PullRequest
1 голос
/ 22 августа 2010

Мне трудно обдумывать модели данных.Позвольте мне начать с демонстрации того, как я объявил бы класс, если бы мне просто нужно было иметь объекты в памяти.

@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, называемом владельцемхотя мне не нужно обращаться к нему в моем коде.Я могу определить обратное отношение saveDice как владельца.Затем, если я пытаюсь определить обратное отношение немедленного ролика как владельца, оно отменяет его как обратное отношение сохраненного кубика.И, конечно же, я не могу установить обратные отношения владельца как к saveDice, так и к непосредственным ролям.

Ответы [ 2 ]

3 голосов
/ 22 августа 2010

Вы не можете делать то, что пытаетесь сделать здесь. Если я вас правильно понимаю, вы хотите, чтобы у кубика были отношения с одним владельцем, но у playerState было два разных сохраненных и непосредственных отношения, каждое из которых было связано с владельцем. CoreData не допустит этого.

Вы, вероятно, должны немного переосмыслить свою модель; возможно, добавьте флаг к вашему объекту SavedDie, указывающий, является ли это «сохраненным» броском или «немедленным» броском. Затем добавьте динамические свойства для извлечения только что сохраненных или немедленных кубиков, основываясь на этом флаге. Одно отношение в каждую сторону. Конечно, есть и другие способы сделать это, если они подходят лучше.

2 голосов
/ 23 августа 2010

Вы не можете сделать это непосредственно в Базовых данных, потому что, в отличие от вашего примера выше, Базовые Данные также должны поддерживать график отношений.

Чтобы понять это, предположим, что вы настраиваете отношения вручную, используя приведенный выше пример кода.Теперь представьте, что у вас есть класс SavedDie, который сохраняется в savedDice и immediateRolls из PlayerState.Если вы хотите, чтобы каждый экземпляр SavedDie ссылался на PlayerState, создать указатель на владелец PlayerState было бы легко, но как узнать, в каком свойстве PlayerState оно хранится. Что еще более важно, как вы можете применитьэто так, что один и тот же объект SavedDie не попал в оба свойства или в два или более отдельных объекта PlayerState?

Базовые данные были созданы для автоматического управления всем этим и использует граф сущностей дляСделай так.Сущности не являются классами.Вместо этого они являются абстрактным представлением в основном отношений между объектами.Граф сущностей не позволит вам иметь одну связь двух сущностей с другой сущностью, потому что было бы невозможно отследить, какие экземпляры живых объектов данных шли друг с другом.

Существует два способа решения вашей проблемы.

(1) Использование наследования сущностей: вы создаете сущность Die и настраиваете все необходимые атрибуты.Затем вы создаете две субэлементы: SavedDie и ImmediateDie.Затем вы устанавливаете отношения:

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, он будет принимать либо PlayerToSavedDie, либо PlayerToImmediateDie в этих отношениях.

Какой из этих методов вы используете, зависит от потребностей вашей модели данных.Если логические объекты Die в одном отношении никогда не переходят в другое, используйте (1).Если сохраненные или непосредственные данные являются важным атрибутом самих логических объектов Die, используйте (2).Если логические объекты Die должны перемещаться между связями и сохраненные или непосредственные данные не являются частью логического объекта Die, используйте (3).

Все это может показаться трудоемким, но вы должны запомнить одинвещь импорта: Отношения так же важны, как и атрибуты !Модель не будет работать, если ее отношения не отражают объекты, события или условия реального мира, которые моделирует модель.Вы должны ожидать, что потратите некоторое время на обдумывание и управление отношениями.

Базовые данные упрощают управление отношениями в сто раз, но все же требуют некоторой работы.

...