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

时间:2009-07-04 07:33:35

标签: c# associations business-objects

假设我正在为制药公司开发一个软件,其中每个'ProductionLine'有多个'Stages',每个阶段有多个'Machines'

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

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

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

(3)StageMachines(表示为舞台指定的多台机器)

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

我设计了以下课程:

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

现在我面临一个困境:

(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对象时应该如何保存机器?

有人能给我一个解决方案吗?

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

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

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

3 个答案:

答案 0 :(得分:1)

虽然它与业务问题无关,但事实上,机器确实与舞台有关联,最好由集合表达。如果你正在使用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.
}

答案 1 :(得分:0)

你已经说过了

  

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

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

答案 2 :(得分:0)

如果您执行以下操作:

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

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

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”是错误的术语。基本上你可以有一个静态方法为每个机器ID创建一个单例。)

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