Entity Framework Core を利用したシンプルなカード型データベース編集アプリケーションのコードを紹介します。
こちらの記事では、ASP.NET Coreでカード型のデータベースアプリケーションを作成する手順を紹介しました。
この記事では、Entity Framework Core を利用して、カード型のデータベースアプリケーションを作成する手順とコードを紹介します。
カード型のデータベース変更アプリケーションは利用する機会も多いため、レコードの表示、編集、追加、削除を合わせたプログラム全体を紹介します。
以下のテーブルを作成してデータを作成します。
id | model | name | class | category | price |
---|---|---|---|---|---|
1 | C-XM01 | モーダンチェア | ホーム | チェア | 56000 |
2 | X-XD05 | ラージデスク | オフィス | テーブル | 87000 |
3 | A-DA40 | ラウンドダイニングチェア | ホーム | チェア | 28000 |
4 | O-XX100 | ナチュラルオフィス | オフィス | チェア | 13800 |
5 | R-D400 | ラウンドダイニングテーブル | ホーム | テーブル | 128000 |
6 | R7000 | ウッドキャビネット | オフィス | その他 | 32000 |
7 | B-200 | リネンベッド | ホーム | ベッド | 184500 |
8 | B-250 | ホワイトダブルベッド | ホーム | ベッド | 324850 |
9 | W-80 | ワーキングチェア | オフィス | チェア | 45000 |
10 | EG-10X | エルゴノミクスデスク | オフィス | テーブル | 88500 |
11 | OC-908 | オーガニックチェア | ホーム | チェア | 56000 |
ASP.NET Core アプリケーションのプロジェクトを作成します。今回は空のプロジェクトから作成しています。
NuGetを利用して、Entity Framework Core のパッケージをインストールします。
Entity Framework CoreとEntity Framework Core SQL Server をインストールします。
詳細な手順はこちらの記事を参照してください。
Microsoft.EntityFrameworkCore.Design パッケージをインストールします。
NuGetパッケージマネージャーコンソールで次のコマンドを実行してインストールすることもできます。
Install-Package Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.Toolsパッケージをインストールします。
NuGetパッケージマネージャーコンソールで次のコマンドを実行してインストールすることもできます。
Install-Package Microsoft.EntityFrameworkCore.Tools
データベースの接続文字列を取得します。
既にデータベースの接続文字列がわかっている場合は、この手順はスキップできます。
サーバーエクスプローラーに新しいデータ接続を追加し、データベースの接続を作成します。
詳細な手順はこちらの記事を参照してください。
接続作成後、サーバーエクスプローラーでデータ接続のノードをクリックして選択し、プロパティウィンドウの[接続文字列]の値をコピーすることで、
接続文字列を取得できます。
NuGetパッケージマネージャーのコンソールで、次のコマンドを実行し、DbContextのコードを生成します。
Scaffold-DbContext 'Data Source=(サーバーのホスト名または、IPアドレス); Initial Catalog=(データベース名)x;Connect Timeout=600;Persist Security Info=True; User ID=(ユーザーID);Password=(パスワード);Max Pool Size=250;Encrypt=False' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
今回のデモでは、以下の接続文字列を利用しています。
Data Source=192.168.0.16; Initial Catalog=iPentecSandBox;Connect Timeout=600;Persist Security Info=True; User ID=******;Password=********
コマンドを実行すると、Modelsディレクトリ内に以下のファイルが作成されます。
(指定ディレクトリへのDbContextクラスのコード生成の詳細はこちらの記事を参照してください。)
以下のコードを用意します。
@page
@using SimpleDBCard.Models
@model SimpleDBCard.Pages.IndexModel
@{
}
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
<title>レコード一覧</title>
<link rel="stylesheet" href="~/Style.css"/>
</head>
<body>
<div>
<h1>レコード一覧</h1>
<a href="~/Insert">レコードの追加</a>
<table>
<thead>
<tr>
<th>id</th>
<th>model</th>
<th>name</th>
<th>class</th>
<th>category</th>
<th>price</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@foreach(ProductsB rec in Model.items){
<tr>
<td>@rec.Id</td>
<td>@rec.Model</td>
<td>@rec.Name</td>
<td>@rec.Class</td>
<td>@rec.Category</td>
<td>@string.Format("{0:#,0}", rec.Price)</td>
<td><a href="~/Update/@rec.Id">編集</a></td>
<td><a href="~/Delete/@rec.Id">削除</a></td>
</tr>
}
</tbody>
</table>
</div>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using SimpleDBCard.Models;
namespace SimpleDBCard.Pages
{
public class IndexModel : PageModel
{
public IEnumerable<ProductsB>? items;
public void OnGet()
{
IPentecSandBoxContext cx = new IPentecSandBoxContext();
items = cx.ProductsBs;
}
}
}
@page "/Update/{id:int}"
@model SimpleDBCard.Pages.UpdateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
<title>レコードの編集</title>
<link rel="stylesheet" href="~/Style.css"/>
</head>
<body>
<div>
<h1>レコードの編集</h1>
<form method="post">
<input type="hidden" asp-for="@Model.item.Id"/>
<div class="EditColumnFrame">
<div class="EditColumn">id</div>
<div class="EditColumn">@Model.item.Id</div>
</div>
<div class="EditColumnFrame">
<div class="EditColumn">model</div>
<div class="EditColumn"><input type="text" asp-for="@Model.item.Model"></div>
</div>
<div class="EditColumnFrame">
<div class="EditColumn">name</div>
<div class="EditColumn"><input type="text" asp-for="@Model.item.Name"></div>
</div>
<div class="EditColumnFrame">
<div class="EditColumn">class</div>
<div class="EditColumn"><input type="text" asp-for="@Model.item.Class"></div>
</div>
<div class="EditColumnFrame">
<div class="EditColumn">category</div>
<div class="EditColumn"><input type="text" asp-for="@Model.item.Category"></div>
</div>
<div class="EditColumnFrame">
<div class="EditColumn">price</div>
<div class="EditColumn"><input type="text" asp-for="@Model.item.Price"></div>
</div>
<div><input type="submit" value="変更"></div>
</form>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using SimpleDBCard.Models;
namespace SimpleDBCard.Pages
{
public class UpdateModel : PageModel
{
[BindProperty]
public ProductsB item { get; set; }
public void OnGet(int id)
{
IPentecSandBoxContext cx = new IPentecSandBoxContext();
item = cx.ProductsBs.Single(i => i.Id == id);
item.Model = item.Model?.Trim();
item.Name= item.Name?.Trim();
item.Class = item.Class?.Trim();
item.Category = item.Category?.Trim();
}
public IActionResult OnPost()
{
if (item != null) {
IPentecSandBoxContext cx = new IPentecSandBoxContext();
cx.ProductsBs.Update(item);
cx.SaveChanges();
}
return RedirectToPage("/Index");
}
}
}
@page
@model SimpleDBCard.Pages.InsertModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
<title>レコードの追加</title>
<link rel="stylesheet" href="~/Style.css"/>
</head>
<body>
<div>
<h1>レコードの追加</h1>
<div>レコードを追加します。</div>
<form method="post">
<div><input type="submit" value="追加"></div>
</form>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using SimpleDBCard.Models;
namespace SimpleDBCard.Pages
{
public class InsertModel : PageModel
{
public void OnGet()
{
}
public IActionResult OnPost()
{
ProductsB rec = new ProductsB();
rec.Name = "新規アイテム";
rec.Model = "NEW-MODEL";
IPentecSandBoxContext cx = new IPentecSandBoxContext();
EntityEntry<ProductsB> ret = cx.ProductsBs.Add(rec);
cx.SaveChanges();
return RedirectToPage("/Update", new { id = rec.Id });
}
}
}
@page "/Delete/{id:int}"
@model SimpleDBCard.Pages.DeleteModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
<title>レコードの削除</title>
<link rel="stylesheet" href="~/Style.css"/>
</head>
<body>
<div>
<h1>レコードの削除</h1>
<div>id = @Model.deleteid のレコードを削除します。</div>
<form method="post">
<input type="hidden" asp-for="@Model.deleteid"/>
<div><input type="submit" value="削除"></div>
</form>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using SimpleDBCard.Models;
namespace SimpleDBCard.Pages
{
public class DeleteModel : PageModel
{
[BindProperty]
public int deleteid { get; set; }
public void OnGet(int id)
{
deleteid = id;
}
public IActionResult OnPost()
{
IPentecSandBoxContext cx = new IPentecSandBoxContext();
ProductsB rec = cx.ProductsBs.Single(i => i.Id == deleteid);
cx.ProductsBs.Remove(rec);
cx.SaveChanges();
return RedirectToPage("/Index");
}
}
}
Table {
margin-left: 1rem;
margin-top: 2rem;
border-collapse: collapse;
}
Table tr th {
border: solid 1px #ff78ae;
padding: 0.1rem 0.25rem 0.1rem 0.25rem;
}
Table tr td {
border: solid 1px #ff78ae;
padding: 0.1rem 0.25rem 0.1rem 0.25rem;
}
.EditColumnFrame {
display:flex;
}
.EditColumn {
min-width:6rem;
}
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();
app.Run();
ファイル構成は下図の状態です。Modelsディレクトリ内に、Scaffold-DbContextコマンドで生成されたコードファイルが配置されています。
データベースからレコードを読み出し、ページにレコードの情報を表示します。
取得したレコードの情報はIEnumerable<ProductsB>型のitems変数に格納します。
ページへの表示は、RazorPage内でforeachループでページモデルクラスのitems変数にアクセスして要素をページに表示します。
pageディレクティブを次の記述に変更し、編集するIDのパラメーターを受け取れる状態にします。
@page "/Update/{id:int}"
変更するレコードの情報はOnGetメソッドで読み込み、ProductsB
クラスのitem
変数に設定します。
Idから1レコードを取得するため、DbSetオブジェクトのSingleメソッドを呼び出して取得します。
取得した値のnchar型のフィールドには空白が含まれるため、Trimメソッドを実行して空白を除去します。
空白の除去処理はDbContextクラスのコードに実装する方法もありますが、
今回は、Scaffold-DbContext
で生成したコードを編集せずに利用したいため、OnGetメソッド内にTrimの処理を実装しています。
IPentecSandBoxContext cx = new IPentecSandBoxContext();
item = cx.ProductsBs.Single(i => i.Id == id);
item.Model = item.Model?.Trim();
item.Name= item.Name?.Trim();
item.Class = item.Class?.Trim();
item.Category = item.Category?.Trim();
idはhiddenフィールドに設定します。
<input type="hidden" asp-for="@Model.item.Id"/>
変更可能なフィールドはinputタグのasp-for
属性にメンバ変数を設定します。
<input type="text" asp-for="@Model.item.Name">
変更内容のデータベースの反映は OnPaseメソッドで実行します。
DbSetオブジェクトの Update()
メソッドを呼び出し、その後DbContextオブジェクトの SaveChanges()
メソッドを呼び出します。
IPentecSandBoxContext cx = new IPentecSandBoxContext();
cx.ProductsBs.Update(item);
cx.SaveChanges();
変更後は /Index
ページにリダイレクトして戻ります。
レコードの挿入は、確認後にテーブルのDbSetオブジェクトのAddメソッドを呼び出し、レコードを挿入します。
挿入したレコードのIDはレコードのオブジェクトのIdプロパティに設定されます。
RedirectToPageメソッドを呼び出し、挿入したレコードの編集画面に遷移します。
pageディレクティブを次の記述に変更し、編集するIDのパラメーターを受け取れる状態にします。
@page "/Delete/{id:int}"
受け取ったIDはページモデルクラスのdeleteidプロパティに挿入します。
[BindProperty]
public int deleteid { get; set; }
public void OnGet(int id)
{
deleteid = id;
}
サブミットボタンがクリックされると、OnPostメソッドが呼び出され、削除するIDのレコードオブジェクトを取得し、
DbSetオブジェクトのRemove()
メソッドを呼び出してレコードを削除します。
IPentecSandBoxContext cx = new IPentecSandBoxContext();
ProductsB rec = cx.ProductsBs.Single(i => i.Id == deleteid);
cx.ProductsBs.Remove(rec);
cx.SaveChanges();
プロジェクトを実行します。Webブラウザが起動し下図のページが表示されます。
レコードの一覧がページに表示されます。編集したいレコードの[編集]リンクをクリックします。
リンクをクリックすると編集ページに遷移します。レコードの内容がテキストボックスに入力された状態になっています。
テキストボックスを編集し、レコードの内容を変更します。変更後[変更]ボタンをクリックします。
/Index
ページに戻ります。レコードの内容が編集できている状態が確認できます。
ページ上部の[レコードの追加]リンクをクリックします。下図のレコードの追加画面が表示されます。[追加]ボタンをクリックします。
レコードが作成され、追加したレコードの編集画面に遷移します。
レコードの内容を編集し[変更]ボタンをクリックします。
レコードが追加できています。
削除したいレコードの[削除]リンクをクリックします。
レコードの削除画面が表示されます。削除するレコードのidの値が表示されています。[削除]ボタンをクリックします。
レコードが削除され、/Index
ページに戻ります。レコードが削除できていることが確認できます。
Entity Framework Core を利用してシンプルなカード型のデータベース編集アプリケーションを作成できました。
Entity Framework Core を利用しない版と比較すると、記述するコード量が大幅に減ります。