5

如果我有三个实体,Project、ProjectRole 和 Person,其中一个 Person 可以是不同项目的成员并处于不同的项目角色(例如“项目负责人”或“项目成员”) - 你将如何建模这种关系?

在数据库中,我目前有以下表格:Project、Person、ProjectRole Project_Person,其中 PersonId 和 ProjectId 作为 PK,ProjectRoleId 作为 FK 关系。

我真的很茫然,因为我提出的所有域模型似乎都违反了一些“DDD”规则。这个问题有什么“标准”吗?

我查看了 Streamlined Object Modeling 并且有一个 Project 和 ProjectMember 的示例,但 Project 中的 AddProjectMember() 会调用 ProjectMember.AddProject()。所以 Project 有一个 ProjectMember 列表,并且每个 ProjectMember 作为回报都有一个对该项目的引用。对我来说看起来有点令人费解。

更新

在阅读了有关此主题的更多信息后,我将尝试以下操作: 在我的领域中有不同的角色,或者更好的模型关系,它们属于某种角色类型。例如,ProjectMember 是一个独特的角色,它告诉我们有关人员在项目中所扮演的关系的一些信息。它包含一个 ProjectMembershipType,它告诉我们更多关于它将扮演的角色。我确实知道人们必须在项目中扮演角色,所以我将模拟这种关系。

可以创建和修改 ProjectMembershipTypes。这些可以是“项目负责人”、“开发人员”、“外部顾问”或其他不同的人。

一个人在一个项目中可以有很多角色,这些角色可以在某个日期开始和结束。这种关系由类 ProjectMember 建模。

public class ProjectMember : IRole
{
    public virtual int ProjectMemberId { get; set; }
    public virtual ProjectMembershipType ProjectMembershipType { get; set; }

    public virtual Person Person { get; set; }
    public virtual Project Project { get; set; }
    public virtual DateTime From { get; set; }
    public virtual DateTime Thru { get; set; }
    // etc...
}

ProjectMembershipType:即。“项目经理”、“开发人员”、“顾问”

public class ProjectMembershipType : IRoleType
{
    public virtual int ProjectMembershipTypeId { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }

    // etc...
}
4

5 回答 5

3

这是我将如何处理它:

class Person
{
  string Name { get; set; }
  IList<Role> Roles { get; private set; }
}

class Role
{
  string Name { get; set; }
  string Description { get; set; }
  IList<Person> Members { get; private set; }
}

class Project
{
  string Name { get; set; }
  string Description { get; set; }
  IList<ProjectMember> Members { get; private set; }
}

class ProjectMember
{
  Project Project { get; private set; }
  Person Person { get; set; }
  Role Role { get; set; }
}

ProjectMember类将它们组合在一起。该模型使您可以灵活地将同一个人分配给具有不同角色的不同项目(例如,他可能是 ProjectA 的开发人员和 ProjectB 的测试人员)。

请不要创建特定于角色的课程 - 该课程已经学到了。

我创建了一个示例应用程序来演示这一点(它也包括关系):

  1. 运行“ bin\debug\RolesRelationshipsSample.exe
  2. 双击库图标以创建实体
  3. 拖放它们以分配适当的关系

随意玩代码。希望你觉得它有用。

于 2009-03-28T14:35:31.430 回答
1

您正在为多对多关系建模:一个项目可以有很多人参与,一个人可以参与多个项目。

您将关系建模为项目角色,它除了作为来自 Person <-> Project 的双向链接之外,还记录了 RoleType 和填充该项目上该 RoleType 的那个人的开始/结束。(注意英语中的“that”是如何代表数据库 FK 或者在代码中是指针/引用?)

由于这些 FK,我们可以在数据库中遵循从 Person 到 Project Role 到 Project 的图表:

select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where a.person_id = ?

或者我们可以从 Project 的另一个方向跟随它:

select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where c.project_id = ?

理想情况下,我们希望能够在 C# 代码中做同样的事情。所以是的,我们希望 Person 有一个列表,Project 有一个列表,并且 ProjectRole 引用一个 Person 和一个 Project。

是的,Project::addPerson( Person& )应该是Project::addProjectRole( ProjectRole& ),除非我们认为这Project::addPerson( Person& )是一种方便的形式:

void Project::addPerson( Person& p ) {
  this.addProjectRole( new ProjectRole( p, &this, RoleType::UNASSIGNED ) ;
}

ProjectRole 没有列表,它具有对 Person 的引用和对 Project 的引用。它还具有作为值的开始日期、结束日期和 RoleType(它要么是一个枚举,要么是一个模拟枚举值的类实例——也就是说,每个枚举类型只有一个对象,它是无状态、不可变和幂等,因此可以在许多 ProjectRoles 之间共享)。

现在这不应该意味着从数据库中检索一个 Person 应该导致整个数据库在代码中的对象图中被具体化;仅在使用时检索的惰性代理可以使我们摆脱这种情况。然后,如果我们当前只关心 Person,而不是他的角色(和项目,我们可以只检索 Person。(例如,NHibernate,我认为这或多或少是无缝的。)

基本上,我认为:

1)这是表示多对多关系的标准方式;2) 一个关系有额外的数据(什么时候,什么样的)是标准的;3)您的想法几乎是正确的,并且在此处获得反馈时非常认真。

于 2009-04-05T12:00:44.867 回答
0

您不会将角色的“描述”与一个人在项目中的角色混淆吗?添加“RoleDescription”概念(可以说是“角色类”)和指代项目中实际人员的“RoleInstance”对象可能会有所帮助。

于 2009-03-27T11:52:39.223 回答
0

您所拥有的是与附加数据、角色的多对多关系。我们有一个类似的结构,除了在我们的例子中一个人可能在一个项目中扮演多个角色,所以我在同样的问题上挣扎。一种解决方案是创建一个扩展 Person 并添加角色属性的 ProjectPerson 类:

public class ProjectPerson : Person
{
    public string Role { get; set; }
}

您的 Project 类现在有一个 ProjectPerson 的集合,但 Person 类有一个 Project 的集合,因为扩展 Project 类以添加角色没有意义。您必须做一些额外的工作(在 ProjectPerson 集合中查找 Person)才能从 Person 的角度找到 Project 中的角色。

第二种解决方案是使用附加数据处理多对多关系的标准方法。创建一个 ProjectRole 类并将其建模为来自 Project 和 Person 的两个一对多关系的多面。也就是说,Project 和 Person 都有一个 ProjectRole 的集合。

重要的是要考虑您的数据访问策略在选择解决方案时对模型的支持程度。您希望避免加载集合需要为集合中的每个对象访问数据库一次或多次的情况。

于 2009-03-27T12:39:43.107 回答
0

似乎有两个主要实体 - 项目和项目成员。项目成员具有“成员角色”和“成员名称”属性。这些属性中的任何一个都可能属于一个域,即可以在查找表中维护的一组值,既方便又用于搜索。假设有人需要有关执行特定角色/工作的所有项目成员的信息。

笔记。查找表可以添加条目,但通常不会更改条目的值。一旦从查找表中选择了一个值,那么它就被认为是拥有表的永久固定装置 - 在这种情况下是项目成员表。

我不希望在任何业务中看到“人员”实体或表,除了上述情况中作为查找表的便利性。人力资源部门将保留一份员工名单,这些员工拥有工资单等所需的特定信息,但除了企业需要知道的人之外,没有什么基本的信息。注意:定位业务流程以识别实体 - 不要虚构。

于 2010-05-29T00:19:25.067 回答