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

今回は、要件定義とシステム構成の結果を踏まえて、MentorApp の データモデル をどう設計するかを見ていきます。

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

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

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

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

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

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

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

プロ太

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

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

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

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

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

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

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

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

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

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

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

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

MentorAppのspec.mdを読む

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

【C#/Blazor】実務Webアプリ開発編 (11) 要件定義の書き方 ~ロール・機能・非機能・対象外をどう整理するか 実務Webアプリ開発編です。 前回の「ソフトウェア開発の全体像」では、要件定義からデプロイまでの流れを俯瞰しました。 https...

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

【C#/Blazor】実務Webアプリ開発編 (12)システム構成を設計する ~アーキテクチャ選定と技術スタック~ 実務Webアプリ開発編です。前回の「要件定義を書く」では、誰が使い、何を作り、何を今回は作らないかを整理しました。 https:...

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

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

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

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

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

各エンティティのフィールド

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

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

  • Id
  • ExternalId(IdPのsub)
  • 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

この4テーブルで、人(User)→ 関係(Mentorship)→ 話題(Topic)→ 発言(Message) の順に文脈が積み上がっているのが分かります。

IDで連鎖しているため、「鈴木さんと田中さんの転職相談での田中さんの発言」を一意に辿れます。

設計上の判断ポイント

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

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

もし User 側に「相手ユーザーのID」や「関係の状態」まで持たせた設計にすると、

  • 一人のメンターが複数のメンティーを担当する場合にフィールドを増やすか
  • User レコードを複数作るか

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

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

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

プロ美

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

プロ太

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

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

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

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

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

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

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

プロ美

Topic がないと Message が全部フラットに並んで、どこからどこまでが一つの相談か分からなくなりそう。

プロ太

そうです。テーマごとに Status を持てるのも、Topic を独立させたからこそです。

Mentorship 全体が続いていても、終わった話題は Closed にできます。

データモデル設計は画面設計の前に行うことが多いです。

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

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

まとめ

  • データモデルの役割:管理する情報の単位と関連を整理すること
  • MentorAppの4エンティティ:User / Mentorship / Topic / Message の役割を分けていること
  • 設計上のポイント:人、関係、話題、発言の責務を混ぜずに履歴と文脈を保つこと

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

4つのエンティティの役割を分けておくことで、あとから画面や実装を考えるときも筋道が通りやすくなります。

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

プロ太

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

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