5

Project、ProjectRole、Person という 3 つのエンティティがあり、Person が異なるプロジェクトのメンバーになり、異なるプロジェクト ロール (「プロジェクト リーダー」や「プロジェクト メンバー」など) になることができる場合、そのような関係をどのようにモデル化しますか? ?

データベースには、現在、次のテーブルがあります: Project、Person、ProjectRole Project_Person、PersonId と ProjectId を PK、ProjectRoleId を FK Relationship として持ちます。

私が思いついたすべてのドメインモデルが「DDD」ルールに違反しているように見えるので、ここで本当に途方に暮れています。この問題の「基準」はありますか?

合理化されたオブジェクト モデリングを見てみたところ、Project と ProjectMember がどのように見えるかの例がありますが、Project の AddProjectMember() は ProjectMember.AddProject() を呼び出します。したがって、Project には ProjectMembers のリストがあり、返される各 ProjectMember には Project への参照があります。私には少し複雑に見えます。

アップデート

この件について詳しく読んだ後、次のことを試してみます:私のドメイン内には、特定の役割タイプの個別の役割、またはより適切にはモデル関係があります。たとえば、ProjectMember は、プロジェクト内で Person が果たす関係について何かを伝える明確な役割です。これには、果たす役割について詳しく説明する 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

多対多の関係をモデル化しています。プロジェクトには多くの人が参加でき、1 人が複数のプロジェクトに取り組むことができます。

この関係を Project Role としてモデリングしています。これは、Person <-> Project からの双方向リンクとして機能するだけでなく、RoleType と、その Project でその RoleType を満たす Person の開始/終了も記録します。(英語の "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 (列挙型、または列挙値を模倣するクラス インスタンスのいずれか) を持ちます。つまり、列挙型ごとに 1 つのオブジェクトのみが存在し、それはステートレス、不変、べき等であるため、多くの ProjectRoles 間で共有可能)。

これは、データベースから Person を取得すると、データベース全体がコード内のオブジェクト グラフで具体化されるという意味ではありません。使用時にのみ取得する遅延プロキシは、それから私たちを救うことができます. 次に、現在、人物のみに関心があり、役割 (およびプロジェクト) に関心がない場合は、人物を取得するだけで済みます (たとえば、NHibernate は多かれ少なかれシームレスにこれを行うと思います)。

基本的に、私は次のように考えています。

1) これは、多対多の関係を表す標準的な方法です。2) リレーションが追加データ (いつ、どのようなもの) を持つことは標準です。3) あなたはほぼ正しい考えを持っており、ここでフィードバックを得ることに誠実に取り組んでいます。

于 2009-04-05T12:00:44.867 に答える
0

あなたが持っているのは、追加のデータ、役割との多対多の関係です。私たちの構造は似ていますが、私たちの場合、人がプロジェクトで複数の役割を担っている可能性があるため、同じ質問に苦労しました。1つの解決策は、Personを拡張し、ロールプロパティを追加するProjectPersonクラスを作成することです。

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

これで、ProjectクラスにProjectPersonのコレクションが含まれますが、Projectクラスを拡張してロールを追加しても意味がないため、PersonクラスにはProjectのコレクションがあります。個人の観点からプロジェクトでの役割を見つけるには、追加の作業を行う必要があります(ProjectPersonコレクションで個人を検索します)。

2番目の解決策は、追加データとの多対多の関係を処理するための標準的な方法です。ProjectRoleクラスを作成し、ProjectとPersonからの2つの1対多の関係の多面としてモデル化します。つまり、ProjectとPersonの両方にProjectRoleのコレクションがあります。

ソリューションを選択する際には、データアクセス戦略がモデルをどの程度サポートするかを検討することが重要です。コレクションをロードするには、コレクション内のオブジェクトごとにデータベースへの1回以上の移動が必要になるシナリオを回避する必要があります。

于 2009-03-27T12:39:43.107 に答える
0

役割の「説明」と、プロジェクトでの役割を混同していませんか? 「RoleDescription」概念 (いわば「役割クラス」) と、プロジェクト内の実際の人物を参照する「RoleInstance」オブジェクトを追加すると役立つ場合があります。

于 2009-03-27T11:52:39.223 に答える
0

プロジェクトとプロジェクト メンバーという 2 つの主要なエンティティがあるようです。プロジェクト メンバーには、属性「メンバー ロール」と「メンバー名」があります。これらの属性はどちらもドメインに属している場合があります。つまり、利便性と検索に使用するためにルックアップ テーブルで保持できる一連の値です。特定の役割/仕事を実行しているすべてのプロジェクト メンバーに関する情報を必要とする人がいると想定されます。

ノート。ルックアップ テーブルにはエントリを追加できますが、通常、エントリの値は変更されません。ルックアップ テーブルから値が選択されると、その値は所有テーブル (この場合はプロジェクト メンバー テーブル) の永続的なフィクスチャと見なされます。

上記の場合のように、ルックアップ テーブルとしての便利さ以外のビジネスで「Person」エンティティまたはテーブルが表示されるとは思いません。人事部門は、給与計算などで必要とされる特定の情報を持っている従業員のリストを保持しますが、ビジネスが知る必要がある人々に関する基本的なものは何もありません。注: ビジネス プロセスを見つけて、エンティティを特定します。でっち上げではありません。

于 2010-05-29T00:19:25.067 に答える