Отношение ко многим объектам в C # - PullRequest
7 голосов
/ 22 апреля 2009

Я работаю над небольшим образовательным проектом для упражнения perst.net.

У нас есть крошечная проблема проектирования, которая заключается в том, как наилучшим образом разрешить связь между двумя классами объектов, то есть участник и чемпионат . Это соотношение многие ко многим, поскольку участник может принимать участие во многих чемпионатах и чемпионатах может иметь несколько участников .

Посоветуйте, пожалуйста, как лучше всего это сделать в C #, должен ли я использовать технический класс "как в реляционной БД"?

Ответы [ 3 ]

9 голосов
/ 22 апреля 2009

Если вы ищете объектно-ориентированный (или доменно-ориентированный подход) подход, тогда третий объект для обработки «соединения» - совершенно неправильный способ сделать это. Вы можете использовать ILists / Enumerables с методами Add ... для обработки этого следующим образом:

public class Participant
{
    private readonly IList<Championship> _championships = new List<Championship>();

    public IEnumerable<Championship> Championships
    {
        get { return _championships; }
    }

    internal void AddChampionship(Championship championship)
    {
        if (!_championships.Contains(championship))
            _championships.Add(championship);
    }
}

public class Championship
{
    private readonly IList<Participant> _participants = new List<Participant>();

    public IEnumerable<Participant> Participants
    {
        get { return _participants; }
    }

    public void AddParticipant(Participant participant)
    {
        if (_participants.Contains(participant)) return;
        _participants.Add(participant);
        participant.AddChampionship(this);
    }
}

Главное здесь - убедиться, что вы управляете отношениями только с одной стороны - например, в этом случае это будет вызвано чемпионатом. AddParticipant ()

4 голосов
/ 22 апреля 2009

Вы можете иметь любые отношения, в которых определенный элемент может иметь несколько элементов, связанных с ним, используя свойства IEnumerable (или некоторой другой коллекции). В вашем примере это будет выглядеть следующим образом:

class Participant {
   public IEnumerable<Championship> Championships { 
      get {
         return _championships;
      }
   }
   private List<Championship> _championships;
}

Некоторые важные вещи, которые нужно иметь в виду:

  • Всегда делайте это свойство только для чтения. Это иногда сбивает с толку людей, особенно если у вас есть что-то изменяемое, например, ICollection, а не IEnumerable. Создание свойства только для чтения не препятствует модификации коллекции , но изменяет весь список .

  • Загрузка стратегий - вы заметите, что в приведенном выше примере коллекция не инициализирована. Обычно вы делаете это либо в конструкторе, либо при первом обращении к свойству (это называется отложенной реализацией) - обычно говоря, отложенная реализация создает некоторую сложность, но может повысить производительность, особенно если эта коллекция используется не часто или у вас много таких типов. свойства.

  • Как правило, хорошей идеей является выбор класса для «удержания» другого класса в случае «многие ко многим» (то есть у участников есть свойства чемпионатов, но у чемпионатов нет свойств участников или наоборот). Это сокращает объем кода, который вы должны написать, и уменьшает сложность и вашу поверхность с вашей базой данных. Если вызов необходим для другого направления, рассмотрите вызов метода, а не свойство. Помните, что «многие ко многим» в реляционном смысле не обязательно означает, что это общий случай использования (как пользователь, я мог бы хотеть только добавлять участников в чемпионаты, а не в чемпионаты для участников)

  • Если ваша коллекция модифицируема, помните, что отправка Save подразумевает, что коллекции под ним также должны быть изменены, если они были изменены. Это может добавить большую сложность (В прошлом я использовал внутренние списки для хранения добавленных / удаленных элементов)

1 голос
/ 22 апреля 2009

Я не уверен, что это работает для вашего дизайна или требований, но это может быть возможно ...

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

...