はじめに
C#でシンプルなToDoリストWebアプリを作ってみます。
DBはローカルのSQL Serverを使います。
Entity Framework Coreのスキャフォールディング (リバース エンジニアリング)という仕組みを使ってDBのテーブル定義からC#側のクラスを自動的に作成してみます。
使う技術スタック
.NET 6.0
ASP.Net Core MVC
Entity Framework Core
使う開発ツール
Visual Studio2022
SQLServer Management Studio
Visual Studioでプロジェクト作成
Create a new project
↓TemplateはASP.NET Core Web App(MVC)を選択
プロジェクト名はToDoList
にして任意の場所に保存。
Frameworlは.Net6.0を選択してCreateボタンを押下。
↓プロジェクトができたら▷ボタンを押下してデバッグしてみる。
↓ASP.NET Core Web App(MVC)のテンプレが立ち上がったらOK
データベースとテーブルの作成
SSMS(SQLServer Management Studio)を立ち上げる。
新しいデータベースを作成する。
データベース名はToDoList
とする。
データベース:ToDoListに以下のDDLを実行してテーブルを作成する。
Create Table [dbo].[ToDo] (
[id] UNIQUEIDENTIFIER DEFAULT NEWID() NOT NULL
,
[ToDo] [nvarchar] (50)
,
[DueDate] [datetime] NOT NULL
,
CONSTRAINT [PK_ToDo] PRIMARY KEY (id)
);
PKが一つしかないシンプルなテーブル定義にしている。
PKであるid
はUUIDで自動採番されるようにする。
テーブルが作成できたら↓の方法でテストデータを登録しておく。(ただしidはUUIDなので値をいれなくていい)
Nugetパッケージの入手
[ツール] メニューで、[NuGet パッケージ マネージャー]>[パッケージ マネージャー コンソール] (PMC) の順に選択
以下のパッケージをインストールする。
Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.Tools
↓Microsoft.EntityFrameworkCore.Design
を実行する時のイメージ
Visual StudioとSQLServerの接続
「表示」→「SQL Server オブジェクトエクスプローラー」
↓こんな感じで、SSMSで作成したDB(ToDoList)が表示されるようにする
SQLServerを右クリックしてプロパティを表示。
General>ConnectionStringから接続文字列をコピー
コピーした接続文字列にカタログ名Initial Catalog=ToDoList
を追加
Data Source=(サーバ名)\\SQLEXPRESS;Initial Catalog=ToDoList(カタログ名);Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False
ソリューションエクスプローラーからappsettings.jsonを選択
↓のようにConnectionStrings
を追加する。
ToDoList
のValueに接続文字列を貼り付ける
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"ToDoList": "Data Source=(サーバ名)\\SQLEXPRESS;Initial Catalog=ToDoList;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" }
}
リバーススキャフォールディング(モデルとコンテキスト作成)
DBToDoList
のテーブルToDo
のテーブル定義を読み取ってC#側にクラスを作っていく。
まずは以下の手順でモデルとコンテキストを作る。
[ツール] メニューで、[NuGet パッケージ マネージャー]>[パッケージ マネージャー コンソール] (PMC) の順に選択
以下のコマンドを入力。
Scaffold-DbContext 'Name=ConnectionStrings:ToDoList' Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context -Tables ToDo
Name=ConnectionStrings:ToDoList
でappsetting.jsonで指定した接続文字列を取得している。
-OutputDir Models
は、作成されるモデルクラスの出力先フォルダを指定。
-ContextDir Context
で、作成されるコンテキストクラスの出力先フォルダを指定。
-Tables ToDo
で、カタログToDoList
のToDoテーブルを読み取ることを指定。
↓こんな感じで、ContextとModelのクラスが生成される。
↓ToDo.csの中身はこんな感じ。
using System;
using System.Collections.Generic;
namespace ToDoList.Models;
public partial class ToDo
{
public Guid Id { get; set; }
public string? ToDo1 { get; set; }
public DateTime DueDate { get; set; }
}
↓ToDoListContext.csの中身
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using ToDoList.Models;
namespace ToDoList.Context;
public partial class ToDoListContext : DbContext
{
public ToDoListContext()
{
}
public ToDoListContext(DbContextOptions<ToDoListContext> options)
: base(options)
{
}
public virtual DbSet<ToDo> ToDos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer("Name=ConnectionStrings:ToDoList");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ToDo>(entity =>
{
entity.ToTable("ToDo");
entity.Property(e => e.Id)
.HasDefaultValueSql("(newid())")
.HasColumnName("id");
entity.Property(e => e.DueDate).HasColumnType("datetime");
entity.Property(e => e.ToDo1)
.HasMaxLength(50)
.HasColumnName("ToDo");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
↓プロジェクト直下のProgram.cs
からDBContextを参照させる。
以下のコードを追加。
/*ここから*/
using Microsoft.EntityFrameworkCore;
using ToDoList.Context;
/*ここまで */
var builder = WebApplication.CreateBuilder(args);
/*ここから*/
builder.Services.AddDbContext<ToDoListContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("ToDoList") ?? throw new InvalidOperationException("Connection string 'ToDoList' not found.")));
/*ここまで*/
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
スキャフォールディング(ビューとコントローラー作成)
モデルとコンテキストの次は、ビューとコントローラーを作成する。
↓ソリューション エクスプローラーで、Controllers フォルダーを右クリックし、[追加] > [新規スキャフォールディング アイテム] の順に選択。
[スキャフォールディングを追加] ダイアログで、[Entity Framework を使用したビューがある MVC コントローラー] > [追加] の順に選択
↓ModelClassにToDo
を、DataContext classにToDoListContext
を選択してAddを押下
テーブルToDo
にCRUDできるか確認する。
ツールバーの▷ボタンを押下し、デバッグを実行する。
トップページが表示されたら、以下のURLにアクセス
https://localhost:(ポート番号)/ToDoList
Create Newを押下してToDoを登録する。
テンプレートのいらない部分削除
Viewa>Shared>_Layout.cshtml
を、以下の通り不要部部分を削除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - ToDoList</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/ToDoList.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<!--a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">ToDoList</a-->
<!--↓コントローラーを更新></-->
<a class="navbar-brand" asp-area="" asp-controller="ToDoList" asp-action="Index">ToDoList</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<!--div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
</ul>
</div-->
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2023 - ToDoList - <!--a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a-->
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Program.cs
のapp.MapControllerRoute
のコントローラーを更新
app.MapControllerRoute(
name: "default",
/* ↓このように更新 pattern: "{controller=Home}/{action=Index}/{id?}"); */
pattern: "{controller=ToDoList}/{action=Index}/{id?}");
以下のファイル・フォルダを削除
Controllers>HomeController.cs
Views>Home
Views>Home>Index.cshtml
Views>Home>Privacy.cshtml
Context>MasterContext.cs
完成!
参考