我正在做一个小型教育项目来锻炼 perst.net。
我们有一个很小的设计问题,就是如何最好地解决两类对象之间的关系,即参与者和冠军。这是一个多对多的关系,因为参与者可以参加许多锦标赛,而锦标赛可以有多个参与者。
请告知如何在 C# 中做到最好,我应该使用“类似关系数据库”的技术课程吗?
我正在做一个小型教育项目来锻炼 perst.net。
我们有一个很小的设计问题,就是如何最好地解决两类对象之间的关系,即参与者和冠军。这是一个多对多的关系,因为参与者可以参加许多锦标赛,而锦标赛可以有多个参与者。
请告知如何在 C# 中做到最好,我应该使用“类似关系数据库”的技术课程吗?
如果您正在寻找面向对象(或领域驱动设计)的方法,那么处理“连接”的第三个对象是完全错误的方法。您可以使用 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()
您可以使用 IEnumerable(或其他一些集合)属性建立任何关系,其中特定项目可以具有与其关联的多个项目。在您的示例中,这将如下所示:
class Participant {
public IEnumerable<Championship> Championships {
get {
return _championships;
}
}
private List<Championship> _championships;
}
一些重要的事情要记住:
始终将此设置为只读属性。这有时会让人们感到困惑,特别是如果你有一些可修改的东西,比如返回的 ICollection 而不是 IEnumerable。将属性设置为只读不会阻止修改集合,但会修改整个列表。
加载策略 - 您会注意到在上面的示例中集合没有初始化。您通常在构造函数中或第一次访问属性时执行此操作(称为延迟实例化) - 一般而言,延迟实例化会增加一些复杂性,但可以提高性能,特别是如果此集合不经常使用或您有很多此类特性。
一般来说,在多对多的情况下,选择一个类来“持有”另一个类是一个好主意(即参与者有冠军属性,但冠军没有参与者属性,反之亦然)。这减少了您必须编写的代码量,并减少了数据库的复杂性和表面积。如果另一个方向需要调用,请考虑方法调用而不是属性。请记住,关系意义上的多对多并不一定意味着这是常见的用例(作为用户,我可能只想将参与者添加到锦标赛而不是锦标赛到参与者)
如果您的收藏是可修改的,请记住,发送 Save 意味着它下面的收藏也应该被修改,如果它们被更改。这会增加很多复杂性(过去,我使用内部列表来存储添加/删除的项目)
我不确定这是否适合您的设计或要求,但有可能......
显然,多对多关系最容易用管理该关系的第三个对象来表示。在您的情况下,它将是一个冠军参与者。与其在您的参与者类中拥有一个持有冠军的集合,反之亦然,而是让他们持有这个第三类的实例。Championparticipant对象管理这种关系。然后可以将其作为联结表直接序列化到数据库中。