【T2e】Entity Framework Core を用いたデータベースへのアクセス(4/6)
| プロジェクトタイプ | C#コンソールアプリ※ |
|---|---|
| プロジェクト名 | T2e |
| ソリューション名 | PIT2 |
| ターゲットフレームワーク | .NET 8.0(長期的なサポート) |
| 最上位レベルのステートメントを使用しない | 使用する(チェックオフ) |
※ 「コンソールアプリ(.NET Framework)」ではないので注意せよ!
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業についてはO/Rマッピングの必要性を参照せよ.
2e-4. Entity Framework Core の基礎
Entity Framework Coreには主に以下の2通りの使い方がある(_).
- Database First
- 既存のデータベースからクラスの定義を作る使い方
- Code First
- 既存のクラス定義からデータベースのテーブル定義を作る使い方
今回はあらかじめ定義済みの「従業員データベース」にアクセスするのでDatabase Firstの使い方を採用する.
では,C#の「コンソールアプリ」タイプのプロジェクトを作成しよう(「コンソールアプリ(.NET Framework)」ではないので注意せよ).
上表に示すように,プロジェクト名はT2eとする.ターゲットフレームワークとして
「.NET 8.0(長期的なサポート)」を選択し,「最上位レベルのステートメントを使用しない」には
チェックが入っていない ことを確認しよう.
プロジェクトを作成したら,NuGetを使って以下のパッケージを検索してインストールしよう.バージョンが選択可能な場合は 「 最新の安定板 」を選択するのを忘れないようにしよう.
| パッケージ名 | 本校執筆時1の安定版 |
|---|---|
Microsoft.EntityFrameworkCore.Design | 8.0.3 |
Npgsql.EntityFrameworkCore.PostgreSQL | 8.0.2 |
Npgsql.EntityFrameworkCore.PostgreSQL.Design | 1.1.0 |
次にデータベースの定義から,それらをプログラム上で使用できるようにするためのクラスを生成する. このためにはコマンドラインでの操作が必要であるが,Visual Studio には PowerShell のコマンドラインターミナルが統合されているので 以降はそれを使用して操作することにしよう.Visual Studio の「表示」メニュー→「Terminal」(もしくは「ターミナル」)をクリックする(_). すると_に示すようなコマンドラインターミナル2が表示されるはずである.これは前出のPowerShellと同等のものである.
まず以降の作業を行う前に,プロジェクトを一度ビルドしておこう.このためにはソリューションエクスプローラーで T2e プロジェクトを右クリック→「ビルド」をクリックする(_).「出力」ウィンドウに「ビルド: 1 正常終了、...」などと表示されれば問題なくビルドができている(_).
以上を確認したら,コマンドラインターミナル2で_に示すコマンドを実行しよう.
なおこのdotnet ~というコマンドを実行する際は, カレントディレクトリを操作対象のプロジェクトのプロジェクトフォルダに変更する必要がある .今回の場合はあらかじめcd を実行しておく必要がある.カレントディレクトリの概念や確認方法,cdコマンドの使用方法などは 2年次の情報基礎演習で学んでいるはず であるためここでの説明は割愛する.プロジェクト名
なお,今回のソリューションに含まれるプロジェクトに1つでもコンパイルエラーがあるとこのコマンドは失敗することがある.このコマンドを実行する際は一つもコンパイルエラーがないことを確認しておくこと.
PS> dotnet ef dbcontext scaffold "Host=localhost;Port=5432;Database=SampleDB_hr;Username=hr_user;Password=n1z3Lo9AQap3" Npgsql.EntityFrameworkCore.PostgreSQL
_のコマンド「dotnet ef dbcontext scaffold」は,既存のデータベースのテーブル定義から各テーブルに対応するクラス定義を生成するためのコマンドである(参考:Reverse Engineering - EF Core - Microsoft Docs).
コマンドライン引数として,接続文字列とデータベースプロバイダーを指定する必要がある.今回は接続文字列として,前節で使用したのと全く同じ接続文字列を使用している.データベースプロバイダーとはデータベースとの接続を担うプログラム部品,つまりはデータベースドライバの指定であるが今回は先ほどインストールした Npgsql.EntityFrameworkCore.PostgreSQL を指定している.
_を実行すると,コマンドラインターミナルに_①のように表示され, このプロジェクトに_②のように複数の .cs ファイルが追加される.
これらの .cs ファイルは,主にデータベース SampleDB_hr に含まれる7個のテーブルに対応するクラス定義である. ためしに TblJugyoin.cs を開いてみよう._のようなクラス定義が含まれていることがわかるだろう.

おおむねリスト2e-2-1で示したようなクラスになっていることがわかるだろう. ちなみにテーブル名とクラス名の対応は_のようになっている.単純な命名規則の変換であることがわかるだろう.
| テーブル名 | クラス名 | 備考 |
|---|---|---|
tbl_bumon | TblBumon | 部門テーブル |
tbl_chiiki | TblChiiki | 地域テーブル |
tbl_jigyosho | TblJigyosho | 事業所テーブル |
tbl_jugyoin | TblJugyoin | 従業員テーブル |
tbl_shokureki | TblShokureki | 職歴テーブル |
tbl_shokushu | TblShokushu | 職種テーブル |
tbl_todofuken | TblTodofuken | 都道府県テーブル |
また_に示すように,これらのほかにもうひとつ, Entity Framework Core においてはデータコンテキストクラスと呼ばれる,そのデータベースに含まれているすべてのテーブルのハブとなるクラスも生成されている.たいていの場合はという名前のクラスとして生成される.今回の場合はデータベース名ContextSampleDbHrContextクラスであり,その定義は SampleDbHrContext.cs に含まれているのでこれを開いてみよう(_).

これがSampleDB_hr用のデータコンテキストクラスにあたる.このクラスには各テーブルに対応するDbSet
実際にこれらのクラスを使ってデータベースにアクセスしてみよう.Entity Framework Core では,
Microsoft.EntityFrameworkCore名前空間のクラスが必要なので,コードの冒頭に_のような
usingディレクティブを追記する必要がある.
| |
では Program.cs に_に示す内容を記述しよう.
| |
前節のリスト2d-4-3に比べるとかなりシンプルになっていることがわかるだろう. しかし実行内容はリスト2d-4-3と全く同じである. ここまで書けたら実行してみよう.実行結果は_のようになる.
jugyoin_no = 100, sei = 孫, mei = 正義 jugyoin_no = 101, sei = 荒木, mei = 飛呂彦 jugyoin_no = 106, sei = 小沢, mei = 一郎 jugyoin_no = 107, sei = 東藤, mei = 大輝 jugyoin_no = 108, sei = 宮沢, mei = 賢治 jugyoin_no = 109, sei = 御坂, mei = 美琴 jugyoin_no = 113, sei = 安倍, mei = 晋三 jugyoin_no = 123, sei = 高橋, mei = 凜 jugyoin_no = 124, sei = 滝野, mei = 智 jugyoin_no = 143, sei = 浜田, mei = 雅功 jugyoin_no = 144, sei = 毛受, mei = 綾乃 jugyoin_no = 146, sei = 鳩山, mei = 一郎 jugyoin_no = 149, sei = 渡辺, mei = 達也 jugyoin_no = 177, sei = 斉藤, mei = 豊 jugyoin_no = 178, sei = 太宰, mei = 治 jugyoin_no = 179, sei = 阿万音, mei = 鈴羽 jugyoin_no = 200, sei = 中村, mei = 一郎 jugyoin_no = 201, sei = 岡部, mei = 倫太郎 jugyoin_no = 202, sei = 白井, mei = 黒子 jugyoin_no = 203, sei = 宮迫, mei = 博之 jugyoin_no = 204, sei = 池田, mei = 功 jugyoin_no = 205, sei = 橋田, mei = 至 jugyoin_no = 206, sei = 福沢, mei = 諭吉
_の①~③で何をしているのかを説明しておこう.
①では今回のデータコンテキストクラスにあたるSampleDbHrContextクラスの変数を作成している.
この時点でPostgreSQLとの通信が開始されている.
②ではLINQを使って従業員テーブル(.TblJugyoinプロパティ)から含まれている全てのデータを取得している.
この場合は全く絞り込みをしていないので,仮にLINQを使わずに var query = context.TblJugyoins と書いても全く同じであるが,
後の説明のためにあえてLINQを使っている.
③では②で取得されたデータの処理を行っている.LINQを使っているので,ここは単なる foreach 文で実装できる.
ここでは取得された従業員の従業員番号(.JugyoinNo),姓(.Sei),名(.Mei)を表示している.
実際にPostgreSQL側で実行されたSQL文も確認しておこう.プログラムを実行直後に,コマンドラインターミナル2で _を実行すると直前に実行されたSQL文を確認することができる(長いのでコピペ推奨).
PS> Get-Eventlog -LogName Application -Source PostgreSQL | where {$_.Message.Contains("execute")} | select -ExpandProperty Message -First 1
_を実行すると_のような出力が得られるはずである.
従業員テーブル(tbl_jugyoin)に対してSELECT文が実行されていることが分かる.
2022-01-12 15:49:06.944 JST [15604] LOG: execute <unnamed>: SELECT t.jugyoin_no, t.buai, t.bumon_no, t.email, t.first_name, t.kanrisha_no, t.kyuyo, t.last_name, t.mei, t.phone_no, t.sei, t.shokushu_no, t.shugyo_bi
FROM tbl_jugyoin AS t
ORDER BY t.jugyoin_no
試しに Program.cs に_に示す内容を追記して絞り込みを指定し,またソート順序も変更してみよう.
| |
_の実行結果は_のようになる. 指定した通りの絞り込みとソートが行われていることが分かる.
jugyoin_no = 149, sei = 渡辺, mei = 達也
kyuyo = 1050000, shugyobi = 2012-01-29
jugyoin_no = 177, sei = 斉藤, mei = 豊
kyuyo = 840000, shugyobi = 2010-04-23
jugyoin_no = 146, sei = 鳩山, mei = 一郎
kyuyo = 1350000, shugyobi = 2009-01-05
jugyoin_no = 201, sei = 岡部, mei = 倫太郎
kyuyo = 1300000, shugyobi = 2008-02-17
jugyoin_no = 108, sei = 宮沢, mei = 賢治
kyuyo = 1200000, shugyobi = 2006-08-17
jugyoin_no = 109, sei = 御坂, mei = 美琴
kyuyo = 900000, shugyobi = 2006-08-16
jugyoin_no = 206, sei = 福沢, mei = 諭吉
kyuyo = 830000, shugyobi = 2006-06-07
jugyoin_no = 204, sei = 池田, mei = 功
kyuyo = 1000000, shugyobi = 2006-06-07
jugyoin_no = 205, sei = 橋田, mei = 至
kyuyo = 1200000, shugyobi = 2006-06-07
jugyoin_no = 101, sei = 荒木, mei = 飛呂彦
kyuyo = 1700000, shugyobi = 2001-09-21
jugyoin_no = 100, sei = 孫, mei = 正義
kyuyo = 2400000, shugyobi = 1999-06-17
また_のコマンドを実行して直前に実行されたSQL文も確認しておこう. コマンドラインターミナルをさきほどから開いたままであれば,コマンドを打ち直さずとも↑キーを押すことで,今まで実行したコマンドの履歴をたどって実行することができる (表示が崩れる場合は何度かCtrl+C(=コントロールキーを押しながらCキー)を押すとよい). _のようにLINQの式に対応したSQL文が実行されていることが分かる.
2022-01-12 15:51:19.978 JST [3704] LOG: execute <unnamed>: SELECT t.jugyoin_no, t.buai, t.bumon_no, t.email, t.first_name, t.kanrisha_no, t.kyuyo, t.last_name, t.mei, t.phone_no, t.sei, t.shokushu_no, t.shugyo_bi
FROM tbl_jugyoin AS t
WHERE t.kyuyo >= 800000.0
ORDER BY t.shugyo_bi DESC
前節と同じように,ユーザーの入力を使った絞り込みも行ってみよう. Entity Framework Core を用いる限りSQLインジェクションを気にする必要はない.LINQによる絞り込みはすべて 有効なC#の式である必要があるため,SQLインジェクションのような任意の文字列をSQL文に組み込まれる恐れは全くない. Program.cs を_に示すように変更しよう.
| |
書き換えたら実行してみよう.実行すると従業員番号の入力を求められるので適当な従業員番号(例えば100)を入力して
Enterキーを押す.実行結果は_のようになる.
対象の従業員番号を入力: 100
jugyoin_no = 100, sei = 孫, mei = 正義
kyuyo = 2400000, shugyobi = 1999-06-17







