C#のEF Coreでモデルクラスを定義する方法を完全ガイド!初心者でもわかるデータベース操作
生徒
「C#でデータベースを使いたいんですけど、Entity Framework Coreって何ですか?」
先生
「Entity Framework Core、略してEF Coreは、C#でデータベースを簡単に扱えるようにしてくれる便利な道具です。データベースの複雑な操作を、C#のクラスを使って簡単に書けるようになるんですよ。」
生徒
「モデルクラスっていうのは、どういうものなんですか?」
先生
「モデルクラスは、データベースのテーブル構造をC#のクラスで表現したものです。例えば、顧客情報を管理するテーブルがあれば、それに対応する顧客クラスを作ります。それでは、基本的な使い方から見ていきましょう!」
1. Entity Framework Coreとモデルクラスとは?
Entity Framework Core(EF Core)は、マイクロソフトが提供するC#のデータベース操作ライブラリです。ORM(Object-Relational Mapping)と呼ばれる技術を使って、データベースのテーブルとC#のクラスを自動的に結びつけてくれます。ORMとは、オブジェクト指向プログラミングとリレーショナルデータベースを橋渡しする技術のことです。
モデルクラスとは、データベースのテーブル構造を表現するC#のクラスのことです。例えば、本を管理するデータベースがあるとします。本には「タイトル」「著者」「価格」といった情報がありますよね。これらの情報を、C#のクラスのプロパティ(データを保持する部分)として定義するのがモデルクラスです。
モデルクラスを定義することで、SQLという難しいデータベース言語を直接書かなくても、C#のコードだけでデータベース操作ができるようになります。これは、まるで日本語を英語に自動翻訳してくれる翻訳機のようなものです。
2. EF Coreの準備とインストール方法
EF Coreを使うには、まず必要なパッケージをプロジェクトにインストールする必要があります。パッケージとは、便利な機能がまとまった部品のようなものです。Visual Studioを使っている場合、NuGetパッケージマネージャーという機能を使って簡単にインストールできます。
必要なパッケージは主に以下の2つです:
Microsoft.EntityFrameworkCore- EF Coreの基本機能Microsoft.EntityFrameworkCore.SqlServer- SQL Serverデータベースを使う場合(他のデータベースを使う場合は対応するパッケージを選択)
Visual Studioのパッケージマネージャーコンソールで以下のコマンドを実行します:
Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer
これで、EF Coreを使う準備が整いました。次は実際にモデルクラスを定義していきます。
3. 基本的なモデルクラスの定義方法
それでは、実際にモデルクラスを定義してみましょう。ここでは、書籍を管理するシンプルなモデルクラスを作成します。モデルクラスは、普通のC#のクラスとほとんど同じです。
以下は、書籍情報を表すBookクラスの例です:
using System;
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public decimal Price { get; set; }
public DateTime PublishedDate { get; set; }
}
このコードを見てみましょう。public class Bookで、Bookという名前のクラスを定義しています。その中に、BookId、Title、Author、Price、PublishedDateという5つのプロパティがあります。
{ get; set; }は、プロパティの値を読み書きできるようにする記述です。getは値を取得する、setは値を設定するという意味です。これにより、book.Title = "吾輩は猫である"のように値を代入したり、string title = book.Title;のように値を取得したりできます。
データベースでは、このBookクラスが「Books」というテーブルに対応し、各プロパティがテーブルの列(カラム)に対応します。BookIdは、データベース内で各書籍を一意に識別するための主キー(プライマリーキー)として機能します。
4. データ型とプロパティの選び方
モデルクラスのプロパティには、適切なデータ型を選ぶことが重要です。データ型とは、データの種類を表すもので、数値、文字列、日付など、さまざまな種類があります。C#とデータベースの両方で、正しいデータ型を使うことで、データの整合性が保たれます。
よく使われるデータ型は以下の通りです:
int- 整数(例:1, 100, -50)。IDや数量に使用string- 文字列(例:"こんにちは"、"書籍タイトル")。名前やテキストに使用decimal- 小数点を含む正確な数値。金額や価格に使用DateTime- 日付と時刻。生年月日や登録日に使用bool- 真偽値(trueまたはfalse)。在庫の有無などに使用
以下は、顧客情報を管理するモデルクラスの例です:
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime RegistrationDate { get; set; }
public bool IsActive { get; set; }
}
このCustomerクラスでは、顧客ID、名前、メールアドレス、登録日、アクティブ状態を表すプロパティを定義しています。IsActiveは、顧客が現在アクティブかどうかをtrueまたはfalseで表します。
5. 主キーの設定とId命名規則
データベースのテーブルには、各行を一意に識別するための主キー(プライマリーキー)が必要です。主キーは、学校の出席番号のようなもので、同じ番号を持つ生徒が2人いないように、データベースでも同じ主キーを持つレコードは存在しません。
EF Coreでは、プロパティ名が「Id」または「クラス名+Id」(例:BookId)の場合、自動的に主キーとして認識されます。これを規約(Convention)と呼びます。規約に従うことで、特別な設定を書かなくても、EF Coreが自動的に適切な設定をしてくれます。
主キーは通常、int型かlong型を使います。データベースに新しいレコードを追加するとき、主キーの値は自動的に増加していくように設定するのが一般的です。これを自動採番(Auto Increment)といいます。
public class Product
{
// 主キー:ProductIdという名前で自動認識される
public int ProductId { get; set; }
public string ProductName { get; set; }
public string Category { get; set; }
public int StockQuantity { get; set; }
}
このProductクラスでは、ProductIdが主キーとして自動的に認識されます。データベースにProductを追加すると、ProductIdは1、2、3...と自動的に番号が振られていきます。
6. Null許容型とRequired属性の使い方
データベースでは、ある項目が「値がない(NULL)」状態を許可するか、必ず値を入れるかを設定できます。C#のモデルクラスでも同様に、プロパティがnull(値がない状態)を許容するかどうかを指定できます。
Null許容型は、データ型の後ろに「?」を付けることで表現します。例えば、int?は「nullを許容する整数」という意味です。文字列(string)は元々null許容型なので、「?」を付ける必要はありません。
また、Required属性を使うと、そのプロパティが必須であることを明示できます。これを使うには、System.ComponentModel.DataAnnotationsという名前空間を追加する必要があります。名前空間とは、クラスや機能を整理するためのフォルダのようなものです。
using System;
using System.ComponentModel.DataAnnotations;
public class Employee
{
public int EmployeeId { get; set; }
[Required]
public string FullName { get; set; }
public string? MiddleName { get; set; } // 中間名は省略可能
[Required]
public string Email { get; set; }
public DateTime? RetirementDate { get; set; } // 退職日は未定の場合あり
}
この例では、FullNameとEmailは[Required]属性が付いているので必須項目です。一方、MiddleNameとRetirementDateは「?」が付いているので、値がなくても構いません。MiddleNameは中間名がない人もいるため、RetirementDateは現役社員の場合は退職日が未定なため、nullを許容しています。
7. データアノテーションによる検証と制約
EF Coreでは、データアノテーション(Data Annotations)という機能を使って、データに制約や検証ルールを設定できます。データアノテーションは、プロパティの上に角括弧で囲んで記述する特別な属性です。
よく使われるデータアノテーションには以下のようなものがあります:
[StringLength(100)]- 文字列の最大長を指定[MaxLength(50)]- 最大長を指定(文字列以外にも使用可)[Range(0, 100)]- 数値の範囲を指定[EmailAddress]- メールアドレスの形式を検証[Phone]- 電話番号の形式を検証
これらの制約を設定することで、間違ったデータがデータベースに保存されるのを防ぐことができます。まるで、お店の入り口で年齢確認をするようなものです。条件を満たさないデータは、データベースに入れません。
using System.ComponentModel.DataAnnotations;
public class BlogPost
{
public int BlogPostId { get; set; }
[Required]
[StringLength(200)]
public string Title { get; set; }
[Required]
[StringLength(5000)]
public string Content { get; set; }
[Range(0, int.MaxValue)]
public int ViewCount { get; set; }
[EmailAddress]
public string AuthorEmail { get; set; }
}
このBlogPostクラスでは、タイトルは最大200文字、本文は最大5000文字に制限されています。閲覧数(ViewCount)は0以上の値のみ許可され、著者のメールアドレスはメールアドレスの形式である必要があります。
8. DbContextクラスでモデルを登録する
モデルクラスを定義しただけでは、EF Coreはそれをデータベースと結びつけることができません。DbContextという特別なクラスを作成して、モデルクラスを登録する必要があります。DbContextは、データベースとの接続を管理し、データの保存や取得を担当する中心的な役割を果たします。
DbContextクラスは、Microsoft.EntityFrameworkCore.DbContextを継承して作成します。継承とは、既存のクラスの機能を引き継ぐことです。その中で、DbSet<モデルクラス名>というプロパティを定義することで、モデルクラスをデータベースのテーブルとして登録します。
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=MyAppDb;Trusted_Connection=True;");
}
}
この例では、AppDbContextという名前のDbContextクラスを作成しています。DbSet<Book>、DbSet<Customer>、DbSet<Product>という3つのプロパティで、それぞれBookクラス、Customerクラス、Productクラスをテーブルとして登録しています。
OnConfiguringメソッドでは、データベースへの接続文字列を設定しています。この例では、ローカルのSQL Serverデータベースに接続する設定になっています。接続文字列は、データベースの場所や名前、認証方法などを指定するための文字列です。
9. ナビゲーションプロパティでリレーションシップを定義
実際のデータベースでは、複数のテーブルが関連を持つことがよくあります。例えば、書籍と著者の関係、注文と顧客の関係などです。EF Coreでは、ナビゲーションプロパティを使って、モデルクラス間の関連(リレーションシップ)を表現できます。
ナビゲーションプロパティには、大きく分けて2種類あります:
- 参照ナビゲーション - 1つの関連オブジェクトを参照(1対1、多対1の関係)
- コレクションナビゲーション - 複数の関連オブジェクトを参照(1対多の関係)。
List<T>やICollection<T>を使用
例えば、1人の著者が複数の本を書くという関係を考えてみましょう。著者クラスには書籍のリスト(コレクション)を、書籍クラスには著者への参照を持たせます。
using System.Collections.Generic;
public class Author
{
public int AuthorId { get; set; }
public string Name { get; set; }
// 1人の著者は複数の本を書く(1対多)
public ICollection<BookItem> Books { get; set; }
}
public class BookItem
{
public int BookItemId { get; set; }
public string Title { get; set; }
// 外部キー
public int AuthorId { get; set; }
// 各本は1人の著者に属する(多対1)
public Author Author { get; set; }
}
この例では、AuthorクラスとBookItemクラスが相互に関連しています。AuthorクラスのBooksプロパティは、その著者が書いたすべての本のコレクションです。BookItemクラスのAuthorプロパティは、その本を書いた著者への参照です。AuthorIdは外部キーと呼ばれ、データベース上で関連を維持するための識別子です。
このようにナビゲーションプロパティを定義することで、author.Booksのように、著者からその著者の本一覧に簡単にアクセスできるようになります。
10. マイグレーションでデータベースを生成する
モデルクラスとDbContextを定義したら、最後に実際のデータベースを生成する必要があります。EF Coreには、マイグレーション(Migration)という機能があり、モデルクラスの定義からデータベースのテーブルを自動的に作成してくれます。
マイグレーションは、モデルクラスの変更履歴を管理する機能です。モデルクラスを変更したときに、その変更をデータベースに反映させることができます。マイグレーションを実行するには、Visual Studioのパッケージマネージャーコンソールで以下のコマンドを実行します。
初回のマイグレーションを作成:
Add-Migration InitialCreate
このコマンドを実行すると、Migrationsフォルダが作成され、その中にマイグレーションファイルが生成されます。マイグレーションファイルには、データベースに対する変更内容が記述されています。
次に、実際にデータベースを生成または更新するには、以下のコマンドを実行します:
Update-Database
このコマンドを実行すると、マイグレーションファイルの内容に基づいて、実際のデータベースにテーブルが作成されます。モデルクラスに新しいプロパティを追加したり、新しいモデルクラスを作成したりした場合は、再度Add-MigrationとUpdate-Databaseを実行することで、データベースに変更を反映できます。
これで、C#のモデルクラスの定義から、実際のデータベースのテーブル作成まで、一連の流れが完了しました。EF Coreを使うことで、難しいSQLを書かなくても、C#のコードだけでデータベース操作ができるようになります。