Как мне разработать классы для отношений «многие ко многим»?

2

Предположим, что я разрабатываю программное обеспечение для фармацевтической компании, где каждый 'ProductionLine' имеет несколько 'Stages', и каждая стадия имеет несколько 'Machines'

Теперь предположим, что я поддерживаю три таблицы для записи Stages и его машин (оставьте ProductionLine в покое для обсуждения).

(1) Этап (основные данные, которые представляют все возможные этапы, которые может иметь любая производственная линия)

(2) Машина (основные данные, которые представляют все возможные машины, которые могут иметь производственные продукты factory)

(3) StageMachines (представляет собой число машин, назначенных для этапа)

Обратите внимание, что на сцене может быть несколько машин, и машина может быть частью нескольких этапов. Но класс Machine не должен иметь список этапов, поскольку он не имеет отношения к домену проблем бизнеса.

У меня есть следующие классы:

public class Stage
    {
        private int _stageId;
        public int StageID
        {
            get { return _stageId; }
            set { _stageId = value; }
        }

        private string _stageName;
        public string StageName
        {
            get { return _stageName; }
            set { _stageName = value; }
        }

        private List<Machine> myVar;        
        public List<Machine> Machines
        {
            get { return myVar; }
            set { myVar = value; }
        }

        public static bool Save(Stage stage)
        {
            //save code goes here...
        }
    }


public class Machine
    {
        private int _machineId;
        public int MachineID
        {
            get { return _machineId; }
            set { _machineId = value; }
        }

        private string _machineName;
        public string MachineName
        {
            get { return _machineName; }
            set { _machineName = value; }
        }

        public Machine()
        {
        }

        public Machine(int id, string name)
        {
            _machineId = id;
            _machineName = name;
        }
    }

Теперь я столкнулся с dillemma:

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

Stage s = new Stage();
            s.Machines.Add(new Machine(1, "Machine#1"));
            s.Machines.Add(new Machine(2, "Machine#2"));
            s.Machines.Add(new Machine(3, "Machine#3"));

            Stage.Save(s);

(2) Как мне поддерживать отношения "многие ко многим" в моем коде? Должен ли я создать третий класс с именем 'StageMachine'? Если я это сделаю, как мне сохранить машины в том случае, когда я создаю объект Stage?

Может ли кто-нибудь дать мне решение?

*** Дополнительный вопрос заключается в том, что при извлечении машин Stage, как и где в nTier я должен делать сопоставление?

Что такое хороший шаблон дизайна в С# для классов, которым необходимо ссылаться на другие классы?

В этой связи обсуждается проблема дизайна класса, но не отвечают на механизм сохранения и извлечения объектов "Машины моего этапа" в дизайне NTier.

Теги:
associations
business-objects

3 ответа

1

Несмотря на то, что он не имеет отношения к бизнес-проблеме, у машины действительно есть связь с этапом, которая лучше всего выражается в коллекции. Если вы используете сопоставитель O/R, я считаю, что самым простым решением является реализация коллекции Stage на Machine, но не публиковать ее публично. Это может предложить другие преимущества позже, например, для отображения свойства Count для представления количества этапов, на которых используется машина. Моим решением было бы что-то вроде:

public class Stage
{
    private List<Machine> _machines = new List<Machine>();

    public IEnumerable<Machine>
    {
        get { return _machines; }
    }

    public void AddMachine(Machine machine)
    {
        _machines.Add(machine);
        machine.AddStage(this);
    }

    public void RemoveMachine(Machine machine)
    {
        _machines.Remove(machine);
        machine.RemoveStage(this);
    }

    // etc.
}

public class Machine
{
    private List<Stage> _stages = new List<Stage>();

    internal void AddStage(Stage stage)
    {
        _stages.Add(stage);
    }

    internal void RemoveStage(Stage stage)
    {
        _stage.Remove(stage);
    }

    // etc.
}
0

Если вы выполните следующее:

s1.Add(new Machine(1, "Machine#1");
s2.Add(new Machine(1, "Machine#1");

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

Machines.Add(New Machine(1, "Machine#1");
s1.Add(Machines[1]);
s2.Add(Machines[1]);

или

s1.Add(MachineFactory.GetOrCreate(1)); // maintains its own Machines[] internally

(Извините, если "factory" здесь неправильный термин. В принципе, у вас может быть статический метод, который создает одноэлемент для каждого идентификатора машины.)

Это все, что вам нужно для многих-ко-многим в терминах ООП, поскольку вы упомянули, что вам не нужно переходить с машины на ее родительский этап. Отдельный класс StageMachine был бы полезен для упрощения выравнивания ваших классов с структурой реляционной базы данных или для облегчения двунаправленного обхода между этапами и машинами без необходимости поддерживать избыточные списки как в классах Machine, так и Stage.

  • 0
    Проблема с классом StageMachine заключается в том, что мне нужно поддерживать отдельные идентификаторы, отслеживать их и т. Д.
0

Вы сказали, что

... Класс машины не должен иметь список этапов, поскольку он не имеет отношения к домену проблем бизнеса.

Не означает ли это, что все, что вам нужно, это отношения "один ко многим" от этапа к машине? В этом случае вам будет достаточно.

  • 0
    Нет. Потому что у меня могут быть сотни машин и этапов. Но когда я создаю машинный объект, мне не нужно знать, к каким стадиям он принадлежит.
  • 0
    Если мне понадобится узнать это позже, я должен вызвать метод Machine.GetStages (), который должен вернуть List <Stage>.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню