この記事は、実務Webアプリ開発編の一記事です。前回の「システム構成を設計する」では、アプリ全体の構成要素と役割の分け方を整理しました。

今回は、要件定義とシステム構成の結果を踏まえて、MentorApp の データモデル をどう設計するかを見ていきます。要件定義・システム構成については以下も参考にしてください。

【C#/Blazor】実務Webアプリ開発編 (11) 要件定義の書き方 ~ロール・機能・非機能・対象外をどう整理するか 実務Webアプリ開発編です。 前回の「ソフトウェア開発の全体像」では、要件定義からデプロイまでの流れを俯瞰しました。 https...
【C#/Blazor】実務Webアプリ開発編 (12)システム構成を設計する ~アーキテクチャ選定と技術スタック~ 実務Webアプリ開発編です。前回の「要件定義を書く」では、誰が使い、何を作り、何を今回は作らないかを整理しました。 https:...

「エンティティ」と「関連」をどう定義し、次の画面設計にどうつなげていくかを整理していきましょう。

以下のような方に役立つ内容となっています。

  • データベース設計で、まず何から整理すればよいか迷っている
  • エンティティと関連の考え方を実例ベースで学びたい
  • どれをエンティティにすればよいか、分け方の判断基準がつかめていない

題材として、MentorApp を使って進めます。

GitHubにドキュメント・コードの一式があります。

今回、spec.md におけるデータモデルをみていきます。

User / Mentorship / Topic / Message の4つが、どういう意味を持ち、どうつながっているかを一緒に整理していきましょう。

プロ太

アプリが動くたびに、データは蓄積・参照・更新が繰り返されます。最初の設計が後々まで影響するため、ここを丁寧に整理しておく価値があります。

データモデルがはっきりすると、画面設計や実装でも迷いにくくなります。一緒に整理していきましょう。

動画も作成しています。

データモデル設計でやること

前回のシステム構成では、データの永続化に EF Core(コードファースト)を用いたリレーショナルデータベース(RDB)を採用しました。

今回はその前提に立ち、ER図(エンティティと関連)をベースに概念レベルのデータモデルを整理していきます。

実装はコードファーストで進めますが、まずはテーブルや C# のクラスに縛られず、「何を管理するか・どうつながるか」を概念として整理することが出発点です。

データモデルとは、アプリが扱う情報を「管理対象となるもの(エンティティ)」と「どう関係するか(関連/リレーションシップ)」で整理したものです。

データモデルは、テーブル設計やコード上のクラス設計の土台になります。

プロ太

データモデルの用語は、DB/C# にそれぞれ対応します。エンティティはテーブル/クラス、属性はカラム/プロパティにあたります。

EF Core のコードファーストでは、C# のクラス定義からテーブルが自動生成されるので、三者はそのままつながります。

データモデル設計では、画面でユーザーに表示したい情報をそのまま並べるのではなく、業務の中で意味のある単位に分けて考えることがポイントです。

最初にエンティティの境界を整理しておくと、後の画面設計でも「この画面で何のデータを表示するか」がスムーズに決められるようになります。

MentorApp では、ユーザー、メンターとメンティーの関係、相談トピック、メッセージ履歴を扱います。これを4つのエンティティに分けています。

  • 何を管理するか:User / Mentorship / Topic / Message の4種類に整理する
  • どうつながるか:1対多の関連(1つの親に複数の子がぶら下がる構造)で、メンター・メンティーの関係やそこでの会話の内容を辿れるようにする
  • なぜ分けるか:人・関係・話題・発言がそれぞれ異なる意味と役割を持ち、混在させると管理しにくくなるため
プロ太

次に、一緒に設計ドキュメントをみながら、MentorAppの具体的なデータモデル設計についてみていきましょう!

MentorAppのspec.mdを読む

要件定義では、ユーザーロール(Admin / Mentor / Mentee)、メンターとメンティーのペアリング、テーマ別の相談管理といった機能要件を整理しました。

さらにシステム構成では、認証に外部IdP(Google認証やMicrosoft Entra Id)を利用することを決めました。データモデルは、それらの要件と構成を前提に設計します。

MentorApp のspec.mdでは、5. データモデル に4つのエンティティと関連がまとめられています。

ここでは、まずデータモデルの定義(ER図・属性・具体例)を確認し、続いて設計上のポイントを解説していきます。

エンティティと関連(ER図)

spec.md では、4つのエンティティとその関連をER図で定義(Mermaidで記述)しています。まず全体像を押さえておきましょう。

  • User は Mentorship に Mentor としても Mentee としても関連する
  • Mentorship は複数の Topic を持つ
  • Topic は複数の Message を持つ

各エンティティの属性

各エンティティが持つ属性を確認しておきましょう。それぞれの役割と保持する情報の意味を整理します。

User(ユーザー) システムを利用するアカウント。ロール(Admin / Mentor / Mentee)により権限が異なる。

  • Id
  • ExternalId(外部認証サービス側のユーザーID)
  • DisplayName
  • Email(IdPから取得)
  • Role(Admin / Mentor / Mentee)
  • CreatedAt

Mentorship(メンタリング関係) Mentor と Mentee のペアリング関係。管理者が作成し、ステータスで進行状態を管理する。

  • Id
  • MentorUserId → User
  • MenteeUserId → User
  • Status(Active / Completed / Cancelled)
  • StartedAt
  • EndedAt(任意)

Topic(相談トピック) Mentorship 内の個別の相談テーマ。Open / Closed のステータスで管理する。

  • Id
  • MentorshipId → Mentorship
  • Title
  • Status(Open / Closed)
  • CreatedAt

Message(メッセージ) Topic 内のチャットメッセージ。追記のみ(編集・削除なし)。

  • Id
  • TopicId → Topic
  • SenderUserId → User
  • Content
  • SentAt

具体例

定義だけでは抽象的なので、具体的なデータでイメージを補いましょう。

ここでは「メンターの鈴木さんとメンティーの田中さんがペアになり、転職相談と学習計画について会話している」状況を例にします。


User

IdExternalIdDisplayNameEmailRole
1entraid-abc123鈴木 太郎suzuki@example.comMentor
2entraid-def456田中 花子tanaka@example.comMentee

Mentorship

IdMentorUserIdMenteeUserIdStatusStartedAtEndedAt
112Active2026-01-10null

Topic

IdMentorshipIdTitleStatus
11転職相談Open
21学習計画Closed

Message

IdTopicIdSenderUserIdContentSentAt
112今の会社を辞めて転職を考えています2026-01-15 10:00
211まず履歴書を整理しましょう2026-01-15 10:30
322週10時間の学習計画を立てたいです2026-01-20 09:00

人(User)→ 関係(Mentorship)→ 話題(Topic)→ 発言(Message) の順にIDで紐づいて連なっているのが分かります。

IDで連鎖しているため、「鈴木さんと田中さんの転職相談での田中さんの発言」を一意に辿れます。例えば「Message の Id=1」を起点にすると以下のように順番に辿れます。

Message の TopicId=1 → Topic の MentorshipId=1 → Mentorship の MentorUserId=1・MenteeUserId=2 → User(鈴木さん・田中さん)

設計上の判断ポイント

ポイント①:「人」と「関係」を別エンティティにする

MentorApp では、User(アカウント)と Mentorship(ペアリング関係)を別エンティティにしています。

もし User 側に「相手ユーザーのID」や「関係の状態」まで持たせた設計にすると、一人のメンターが複数のメンティーを担当する場合に、

  • 属性を増やすか
  • User レコードを複数作るか

という構造的な問題が生じます。

Mentorship を独立したエンティティにすることで、ペアリングの数だけ Mentorship レコードを追加するだけで済むようになります。

User レコードには手を加えず、過去のペアリング履歴もデータとして自然に残ります。

プロ美

User に「相手ユーザーのID」や「関係の状態」まで持たせる設計はよくないってことだね…。

プロ太

そうですね。「こうしなかったらどうなるか」を考えることが、設計判断を言語化するときの手がかりになります。

なお、User に ExternalId(外部IdPのユーザーID)を持たせているのは、認証に外部IdPを使うと決めたからです。

IdP 側に認証情報を委ね、アプリ側では自前の Id で管理することで、IdP の違いを吸収できます。

ポイント②:会話を話題単位で区切る

Topic を設けることで、Mentorship 内の相談テーマごとに状態を独立して管理できます。「転職相談は終了、学習計画は継続中」のような状態を自然に表現できます。

Topic を設けず Mentorship 直下に Message を並べた場合、全発言がフラットに積み重なり、どこからどこまでが一つの相談かを追いにくくなります。

また「この話題は解決済み」という区切りをデータで表現する手段もなくなります。

なお、Message が「追記のみ(編集・削除なし)」という制約は、要件定義で決定したものです。

この制約があることで、データモデル上も更新日時や削除フラグが不要になり、Message の属性をシンプルに保てています。

概念レベルのデータモデル(エンティティと関連の大枠)は、画面設計より先に整理することが多いです。

一方、属性レベルの詳細は画面設計と並行して詰めていくのが一般的です。

実際には「各機能の画面で何を表示するか」を意識しながら進めるため、互いに影響しあい、設計の途中で行き来しながら固めていくことも珍しくありません。

データモデルは単なる保存先ではなく、画面・権限・業務ルールの共通土台なのです。

画面に引きずられて後から整えるのではなく、業務の意味を軸に設計することで、後続の画面設計や実装が安定します。

まとめ

データモデルは、アプリの情報をきれいに保存するためだけでなく、業務のルールを整理するための土台でもあります。

4つのエンティティの役割を分けておくことで、あとから画面や実装を考えるときもスムーズに進めやすくなります。

次回は、このデータモデルを踏まえて、画面一覧・画面遷移・アクセス制御をどう設計するかを見ていきます。

プロ太

データモデルは、画面にも実装にもつながる設計の土台です。引き続き、画面まわりの設計を一緒に学んでいきましょう!

ABOUT ME
プロ太
ソフトウェア開発を楽しく、効率的に行う方法を追求しています。 開発者の視点から技術的課題に向き合い、「純粋な技術的興味に基づく探求」と「実践的な課題解決」という二つの柱を両輪として活動しています。