データベース操作をコントローラーから切り離す
スキャフォールディングを使ってコントローラーとビューを作成すると、コントローラーの中でデータベースの操作を行うコードが生成されますが、MVC ではデータベースの操作をコントローラーの中で行わないのが一般的です。
今回はデータベースの処理をコントローラーから切り離して、データベースの処理を行うサービスを別途作成します。
作成したサービスは、DI(Dependency Injection)の機能を使って登録します。
DI とはオブジェクトに対して外部から機能を追加する仕組みで、オブジェクトの独立性を高める効果があり、日本語では「依存関係の挿入」とか「依存性の注入」などと訳されます。
ASP.NET では DI が標準で組み込まれており、前回作成したプログラムでも DI の技術が使われています。
DI に関する詳しい内容は、以下のマイクロソフトの公式サイトを参照してください。
新規にプロジェクトを作成する
今回は、新規にプロジェクトを作成し、コントローラーやビューはスキャフォールディングを使わないで、自分で作成することとします。
データベースの内容は、前回の記事で作成した構成で、新規のプロジェクト内に作成します。
今回作成するプロジェクト名は、「MvcApp3」とします。
NuGetパッケージのインストール
今回のプログラムでは、コントローラーとビューの作成にスキャフォールディングは使用しないので、以下の4つのパッケージをインストールします。
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design は不要です。
データベースとの接続情報を登録する
NuGetパッケージのインストールが完了したら、データベースに接続するための設定を行います。
ソリューションエクスプローラーの下の方にある「appsettings.json」に、8~10行目の内容を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "ConnectionStrings": { "MvcAppDb": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MvcAppDb" }, "AllowedHosts": "*" } |
モデルクラスとDbContextクラスを作成する
メニューバーから「ツール」→「NuGetパッケージマネージャー」→「パッケージマネージャーコンソール」を選択し、パッケージマネージャーコンソールを起動します。
パッケージマネージャーコンソールから以下のスキャフォールディングコマンドを使って、モデルクラスと DbContextクラスを作成します。
Scaffold-DbContext 'Name=ConnectionStrings:MvcAppDb' Microsoft.EntityFrameworkCore.SqlServer -ContextDir Data -OutputDir Models/Entity -NoOnConfiguring
Program.csにデータベース接続情報を追加する
スキャフォールディングコマンドで、「-NoOnConfiguring」オプションを指定したので、「Program.cs」にデータベースの接続情報を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
using Microsoft.EntityFrameworkCore; using MvcApp3.Data; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddDbContext<MvcAppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("MvcAppDb")) ); var app = builder.Build(); ~ 以下略 ~ |
インターフェイスと実装クラスを作成する
データベースの操作をするインターフェイスと実装クラスを新しく作成します。
インターフェイスは、AddScoped()メソッドの型として使用するため必須です。
今回は、プロジェクト直下に「Service」というフォルダーを作成し、そこにインターフェイスと実装クラスを配置します。
インターフェイス名は「IEmpsService.cs」、実装クラス名は「EmpsImpl.cs」とします。
1 2 3 4 5 6 7 8 9 |
using MvcApp3.Models.Entity; namespace MvcApp3.Services { public interface IEmpsService { public Task<List<Emp>> Index(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using Microsoft.EntityFrameworkCore; using MvcApp3.Data; using MvcApp3.Models.Entity; namespace MvcApp3.Services { public class EmpsImpl : IEmpsService { private readonly MvcAppDbContext _context; public EmpsImpl(MvcAppDbContext context) { _context = context; } public async Task<List<Emp>> Index() { return await _context.Emps.ToListAsync(); } } } |
DIコンテナーにサービスを追加する
Program.cs 内の DIコンテナーに、作成したサービスを追加します。
以下のように、Program.cs 内に、Service. AddScoped()メソッドを追加します。
Services.AddScoped<インターフェイス名, 実装クラス>()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
using Microsoft.EntityFrameworkCore; using MvcApp3.Data; using MvcApp3.Extensions; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddDbContext<MvcAppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("MvcAppDb")) ); builder.Services.AddScoped<IEmpsService, EmpsImpl>(); var app = builder.Build(); ~ 以下略 ~ |
AddScoped()メソッドの詳しい内容は、以下のマイクロソフト公式サイトを参照してください。
コントローラーとビューを作成する
実際にデータベースの操作を行う実装クラスまで作成したら、次にそれを使うコントローラーとビューを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using Microsoft.AspNetCore.Mvc; using MvcApp3.Services; namespace MvcApp3.Controllers { public class EmpsController : Controller { private readonly IEmpsService _empsService; public EmpsController(IEmpsService empsService) { _empsService = empsService; } public async Task<IActionResult> Index() { return View(await _empsService.Index()); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@model IEnumerable<Emp> @{ ViewData["Title"] = "Index"; } <h1>Index</h1> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.Name)</th> <th>@Html.DisplayNameFor(model => model.ZipCode)</th> <th>@Html.DisplayNameFor(model => model.Address)</th> <th>@Html.DisplayNameFor(model => model.Birthday)</th> <th>@Html.DisplayNameFor(model => model.Email)</th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td>@Html.DisplayFor(modelItem => item.Name)</td> <td>@Html.DisplayFor(modelItem => item.ZipCode)</td> <td>@Html.DisplayFor(modelItem => item.Address)</td> <td>@Html.DisplayFor(modelItem => item.Birthday)</td> <td>@Html.DisplayFor(modelItem => item.Email)</td> </tr> } </tbody> </table> |
プログラムを実行する
プログラムを実行して、表示されたホーム画面のアドレスバーに「https://localhost:<ポート番号>/Emps」と入力します。
ポート番号は、環境によって異なります。
データベースの内容を表示する画面に遷移します。