8

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

我们有一个很小的设计问题,就是如何最好地解决两类对象之间的关系,即参与者冠军。这是一个多对多的关系,因为参与者可以参加许多锦标赛,而锦标赛可以有多个参与者

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

4

3 回答 3

10

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

于 2009-04-22T11:15:57.987 回答
4

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

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

一些重要的事情要记住:

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

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

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

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

于 2009-04-22T11:13:28.117 回答
1

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

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

于 2009-04-22T11:12:07.713 回答