kit*_*une 5 entity-relationship domain-driven-design
如果我有三个实体,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有一个ProjectMembers列表,每个ProjectMember都有一个Project的引用.看起来有点费解我.
更新
在阅读了有关此主题的更多信息后,我将尝试以下内容:在我的域中存在特定角色类型的不同角色或更好的模型关系.例如,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...
}
Run Code Online (Sandbox Code Playgroud)
ProjectMembershipType:即."项目经理","开发人员","顾问"
public class ProjectMembershipType : IRoleType
{
public virtual int ProjectMembershipTypeId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
// etc...
}
Run Code Online (Sandbox Code Playgroud)
您正在建模多对多关系:一个项目可以有很多人参与其中,而一个人可以参与多个项目。
您将关系建模为项目角色,该角色除了充当 Person <-> Project 的双向链接之外,还记录 RoleType 以及在该项目上填充该 RoleType 的该 Person 的开始/结束。(请注意英语中的“that”如何代表数据库 FK,或者在代码中代表指针/引用?)
由于这些 FK,我们可以在数据库中遵循从“人员”到“项目角色”再到“项目”的图表:
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 = ?
Run Code Online (Sandbox Code Playgroud)
或者我们可以从 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 = ?
Run Code Online (Sandbox Code Playgroud)
理想情况下,我们希望能够在 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 ) ;
}
Run Code Online (Sandbox Code Playgroud)
ProjectRole 没有列表,它有对 Person 的引用和对 Project 的引用。它还具有作为值的开始日期、结束日期和 RoleType(它要么是枚举,要么是模仿枚举值的类实例——也就是说,每个枚举类型只有一个对象,并且它是无状态、不可变和幂等,因此可以在许多项目角色之间共享)。
现在,这不应该意味着从数据库中检索 Person 会导致整个数据库在代码的对象图中具体化;仅在使用时检索的惰性代理可以帮助我们避免这种情况。然后,如果我们当前只关心这个人,而不是他的角色(和项目),我们就可以检索这个人。(例如,NHibernate,我认为这或多或少是无缝的。)
基本上,我认为:
1)这是表示多对多关系的标准方式;2) 关系有附加数据(何时、何种类型)是标准的;3)你的想法几乎是正确的,并且在这里认真地获取反馈。