【问题标题】:Many to many object to object relation in C#C#中的多对多对象到对象关系
【发布时间】:2010-10-21 01:41:37
【问题描述】:

我正在做一个小型教育项目来锻炼 perst.net。

我们有一个很小的设计问题,那就是如何最好地解决两类对象之间的关系,即参与者和冠军。这是一个多对多的关系,因为 participant 可以参加许多 championships 并且 championships 可以有多个 participants .

请告知如何在 C# 中做到最好,我应该使用“类似关系数据库”技术类吗?

【问题讨论】:

    标签: c# .net oop object-oriented-database


    【解决方案1】:

    我不确定这是否适合您的设计或要求,但有可能......

    显然,多对多关系最容易用管理该关系的第三个对象来表示。在您的情况下,它将是 冠军参与者。与其在您的参与者类中拥有一个持有冠军的集合,反之亦然,而是让他们持有这个第三类的实例。 championshipparticipant 对象管理这种关系。然后可以将其作为联结表直接序列化到数据库中。

    【讨论】:

      【解决方案2】:

      您可以使用 IEnumerable(或其他一些集合)属性建立任何关系,其中特定项目可以有多个与之关联的项目。在您的示例中,如下所示:

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

      需要牢记的一些重要事项:

      • 始终将此设置为只读属性。这有时会让人们感到困惑,特别是如果你有一些可修改的东西,比如返回的 ICollection 而不是 IEnumerable。将属性设为只读不会阻止修改 集合,但会修改 整个列表。

      • 加载策略 - 您会注意到在上面的示例中,集合未初始化。您通常在构造函数中或第一次访问属性时执行此操作(称为延迟实例化) - 一般而言,延迟实例化会增加一些复杂性,但可以提高性能,特别是如果此集合不经常使用或您有很多此类属性。

      • 一般来说,在多对多的情况下,选择一个类来“持有”另一个类是个好主意(即参与者有冠军属性,但冠军没有参与者属性,反之亦然)。这减少了您必须编写的代码量,并降低了数据库的复杂性和表面积。如果另一个方向需要调用,请考虑方法调用而不是属性。请记住,关系意义上的多对多并不一定意味着这是常见的用例(作为用户,我可能只想将参与者添加到锦标赛而不是锦标赛到参与者)

      • 如果您的集合是可修改的,请记住,发送保存意味着它下面的集合如果被更改也应该被修改。这会增加很多复杂性(过去,我使用内部列表来存储添加/删除的项目)

      【讨论】:

        【解决方案3】:

        如果您正在寻找面向对象(或领域驱动设计)的方法,那么处理“连接”的第三个对象是完全错误的方法。您可以使用 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);
            }
        }
        

        这里的关键是确保您只从一侧管理关系 - 例如。在这种情况下,将通过调用 Championship.AddParticipant()

        【讨论】:

        • 很好的答案!最后一句话很关键......你应该让它变得粗体! +1
        猜你喜欢
        • 2010-12-07
        • 1970-01-01
        • 1970-01-01
        • 2020-12-17
        • 1970-01-01
        • 2017-01-22
        • 2022-01-17
        • 2021-08-26
        相关资源
        最近更新 更多