我应该如何设计多对多关系的类?

时间:2022-10-04 11:41:52

Suppose I am developing a software for a pharmaceutical company where each 'ProductionLine' has multiple 'Stages' and each Stage has multiple 'Machines'

假设我正在为一家制药公司开发一个软件,每个'ProductionLine'都有多个'Stages',每个Stage都有多个'Machines'

Now suppose I am maintaining three tables to record Stages and its Machines (leave the ProductionLine away for the shake of the discussion).

现在假设我正在维护三个表格来记录阶段及其机器(让ProductionLine远离讨论的动摇)。

(1) Stage (Basic data which represents all possible Stages any production line can have)

(1)阶段(表示任何生产线可能具有的所有可能阶段的基本数据)

(2) Machine (Basic data which represents all possible machines the production-factory can have)

(2)机器(代表生产工厂可能拥有的所有可能机器的基本数据)

(3) StageMachines (Represents a number of machines assigned for a stage)

(3)StageMachines(表示为舞台分配的多台机器)

Please note that, a stage can have multiple machines and a machine can be a part of multiple stages. But a Machine class shouldn't have a list of Stages, coz it is irrelevant accoring to the bussiness problem domain.

请注意,一个舞台可以有多台机器,一台机器可以是多个阶段的一部分。但是机器类不应该有阶段列表,因为它与业务问题域无关。

I have the following classes designed:

我设计了以下课程:

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;
        }
    }

Now I am facing a dillemma:

现在我面临一个困境:

(1) When I am creating a Stage, I have to choose some Machines from all machines and save the data. How should I handle this in my code, coz then I should be able to write the following code:

(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) How should I maintain this many-to-many relationship in my code? Should I create a third class named 'StageMachine'? If I do so, how should I save the machines in when I am creating an Stage object?

(2)我应该如何在代码中保持这种多对多的关系?我应该创建一个名为“StageMachine”的第三个类吗?如果我这样做,在创建Stage对象时应该如何保存机器?

Can anyone give me a solution?

有谁能给我一个解决方案?

*** An additional question is, when retrieving the machines of a Stage, how and where in the nTier I should do the mapping?

***另一个问题是,在检索舞台的机器时,我应该如何以及在哪里进行映射?

What is a good design pattern in C# for classes that need to reference other classes?

对于需要引用其他类的类,C#中的优秀设计模式是什么?

This link discusses the class design problem but don't answer the Saving and Retrieving mechanism of Machines of my Stage object in the NTier design.

此链接讨论了类设计问题,但没有回答NTier设计中我的Stage对象的机器的保存和检索机制。

3 个解决方案

#1


Although its irrelevant to the business problem, a Machine does in fact have an association to a Stage that is best expressed by a collection. If you're using an O/R mapper, I think the easiest solution is to implement the Stage collection on Machine but don't expose it publicly. This may offer other advantages later, on such as exposing the Count property to represent how many stages a machine is used on. My solution would be something like:

虽然它与业务问题无关,但事实上,机器确实与舞台有关联,最好由集合表达。如果你正在使用O / R映射器,我认为最简单的解决方案是在机器上实现Stage集合,但不要公开它。这可能会在以后提供其他优点,例如公开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.
}

#2


You've said that

你已经说过了

... a Machine class shouldn't have a list of Stages, coz it is irrelevant accoring to the bussiness problem domain.

...机器类不应该有阶段列表,因为它与业务问题域无关。

Does that not mean all you need is a 1-to-many relationship from stage to machine? In that case what you've got would be enough.

这并不意味着您需要的只是从一个阶段到一个机器的一对多关系吗?在那种情况下,你所拥有的就足够了。

#3


If you do the following:

如果您执行以下操作:

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

you will end up with two different objects representing the same machine data. Instead, you can have a List of machines or a MachineFactory that provides you with the same object reference, given a machine ID, so:

最终会得到两个代表相同机器数据的不同对象。相反,您可以拥有一个机器列表或一个MachineFactory,它在给定机器ID的情况下为您提供相同的对象引用,因此:

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

or

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

(Sorry if "factory" is the wrong term here. Basically you can have a static method that creates a singleton for each machine ID.)

(对不起,如果“factory”是错误的术语。基本上你可以有一个静态方法为每个机器ID创建一个单例。)

That's all you need for many-to-many in OOP terms, since you mentioned that you don't need to traverse from a Machine to its parent Stage. A separate StageMachine class would be useful to keep your classes aligned with the relational database structure for simplicity, or to allow easier bi-directional traversal between stages and machines without needing to maintain redundant lists in both the Machine and Stage classes.

这就是OOP术语中多对多所需要的,因为您提到您不需要从机器遍历到其父级。为简单起见,单独的StageMachine类可以使您的类与关系数据库结构保持一致,或者允许在阶段和机器之间更容易地进行双向遍历,而无需在Machine和Stage类中维护冗余列表。

#1


Although its irrelevant to the business problem, a Machine does in fact have an association to a Stage that is best expressed by a collection. If you're using an O/R mapper, I think the easiest solution is to implement the Stage collection on Machine but don't expose it publicly. This may offer other advantages later, on such as exposing the Count property to represent how many stages a machine is used on. My solution would be something like:

虽然它与业务问题无关,但事实上,机器确实与舞台有关联,最好由集合表达。如果你正在使用O / R映射器,我认为最简单的解决方案是在机器上实现Stage集合,但不要公开它。这可能会在以后提供其他优点,例如公开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.
}

#2


You've said that

你已经说过了

... a Machine class shouldn't have a list of Stages, coz it is irrelevant accoring to the bussiness problem domain.

...机器类不应该有阶段列表,因为它与业务问题域无关。

Does that not mean all you need is a 1-to-many relationship from stage to machine? In that case what you've got would be enough.

这并不意味着您需要的只是从一个阶段到一个机器的一对多关系吗?在那种情况下,你所拥有的就足够了。

#3


If you do the following:

如果您执行以下操作:

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

you will end up with two different objects representing the same machine data. Instead, you can have a List of machines or a MachineFactory that provides you with the same object reference, given a machine ID, so:

最终会得到两个代表相同机器数据的不同对象。相反,您可以拥有一个机器列表或一个MachineFactory,它在给定机器ID的情况下为您提供相同的对象引用,因此:

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

or

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

(Sorry if "factory" is the wrong term here. Basically you can have a static method that creates a singleton for each machine ID.)

(对不起,如果“factory”是错误的术语。基本上你可以有一个静态方法为每个机器ID创建一个单例。)

That's all you need for many-to-many in OOP terms, since you mentioned that you don't need to traverse from a Machine to its parent Stage. A separate StageMachine class would be useful to keep your classes aligned with the relational database structure for simplicity, or to allow easier bi-directional traversal between stages and machines without needing to maintain redundant lists in both the Machine and Stage classes.

这就是OOP术语中多对多所需要的,因为您提到您不需要从机器遍历到其父级。为简单起见,单独的StageMachine类可以使您的类与关系数据库结构保持一致,或者允许在阶段和机器之间更容易地进行双向遍历,而无需在Machine和Stage类中维护冗余列表。