[ASP.NET Core] Blazor Server 入門 (EF Core + SQL Server 編)
こんにちは、kenzauros です。
前回 はインストールとセットアップを行ったので、今回は Entity Framework Core (EFCore) を使って SQL Server に接続してみます。
SQLite で始める例も多いですが、今回はより実践的になるよう、既存のデータベース (SQL Server) に接続することを想定します。
前提
環境
前回の続きを想定します。
- Visual Studio Code 1.38.1
- 拡張機能 C# 1.21.2
- 拡張機能 C# XML Documentation Comments 0.1.8
- .NET Core 3.0 (SDK 3.0.100)
- Microsoft.AspNetCore.Blazor.Templates 3.0.0
- Microsoft.EntityFrameworkCore.SqlServer 3.0.0
冒頭に書いたとおり、データベースへの接続と操作には Entity Framework Core (EFCore) を使います。リファレンスは下記のページです。
データベース
下記のようなデータベースが既存で存在することを仮定します。
- hogehoge データベース
- dbo スキーマ
- D_Users テーブル
- id 列 (integer, PK)
- name 列 (nvarchar(256))
すなわち、下記の SQL で dbo.D_Users
テーブルの中身が取得できる想定です。
USE hogehoge;
SELECT id, name FROM dbo.D_Users;
以後、データベース構造やテーブルについては、ご自身の環境で読み替えてください。
実践
パッケージのインストール
Microsoft.EntityFrameworkCore.SqlServer
をインストールします。最新バージョンでよければ --version
オプションは不要です。
また前回構築したフォルダー構成のため、 src
フォルダーを指定していますが、ワークスペース直下にプロジェクトがある場合は src
部分の指定は不要です。
$ dotnet add src package Microsoft.EntityFrameworkCore.SqlServer --version 3.0.0
既定で最新のリリースバージョンがインストールされるはですが、必要に応じてバージョンを指定してください。最新のバージョン番号は NuGet で確認できます。 (執筆時点では 3.0.0
)
EF Core のツールも Microsoft.EntityFrameworkCore.Tools
でインストールしておきます。
$ dotnet add src package Microsoft.EntityFrameworkCore.Tools
モデルクラスの準備
Users テーブルに対応するモデルとして User
クラスを作成します。今回は Data/User.cs
としました。
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MyFirstBlazorApp.Data
{
/// <summary>
/// ユーザー
/// </summary>
[Table("D_Users", Schema = "dbo")]
public class User
{
/// <summary>
/// ID
/// </summary>
/// <value></value>
[Key]
[Column("id")]
public string Id { get; set; }
/// <summary>
/// Name of the user
/// </summary>
/// <value></value>
[Column("name")]
public string Name { get; set; }
}
}
このようにモデルと DB の定義名が違う場合は Table
, Column
などのデータ注釈で DB の定義名を指定します。主キー (PK) は [Key]
で指定しておきます。
なおプログラム上、必要のないカラムは特に定義する必要はありません。
ちなみにモデルクラスは既存のデータベースから対象のテーブルを指定してリバースエンジニアリングすることも可能です。
モデルのリバース エンジニアリングを行う - ASP.NET Core - 既存のデータベース - EF Core の概要 | Microsoft Docs
テーブル数が多い場合などは、工数の削減につながりそうです。
DbContext の準備
Data/HogehogeDbContext.cs
を作成し、データベースコンテキストを定義します。このあたりは従来の Entity Framework と同様です。
コンテキストのファイル名 (クラス名) は任意でかまいません。
using Microsoft.EntityFrameworkCore;
namespace MyFirstBlazorApp.Data
{
public class HogehogeDbContext : DbContext
{
public HogehogeDbContext(DbContextOptions<HogehogeDbContext> options)
: base(options)
{
}
public virtual DbSet<User> Users { get; set; }
}
}
DbSet<T>
で User
モデルのデータセットを定義すれば、 context.Users
で D_Users
テーブルのデータにアクセスできるようになります。
DB 接続情報の定義
DB の接続文字列 (ConnectionString) は appsettings.json
の ConnectionStrings
に定義して読み込めますが、今回は開発環境なのでとりあえず appsettings.Development.json
に定義します。
{
"ConnectionStrings": {
"HogehogeConnection": "Data Source=サーバー;Initial Catalog=hogehoge;Persist Security Info=True;User ID=ユーザー;Password=パスワード"
},
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
データサービスの準備
作った HogehogeDbContext
を直接ビューから呼び出してもいいのですが、依存関係を減らすため、データサービスを作成します。
Blazor テンプレートで生成される WeatherForecastService
を真似て作ります。
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace MyFirstBlazorApp.Data
{
public class HogehogeDataService
{
// DbContext being injected by DI
HogehogeDbContext _Context { get; }
public HogehogeDataService(HogehogeDbContext context) =>
_Context = context;
/// <summary>
/// Gets the entire user list.
/// </summary>
/// <returns></returns>
public Task<List<User>> GetUsersAsync() =>
_Context.Users
.OrderBy(x => x.Id)
.ToListAsync();
}
}
ここでは D_Users
テーブルのデータを単純にすべて取得するだけのメソッドを定義しています。
この _Context
は DI (依存性注入) により、コンストラクター経由で実際のインスタンスが設定されます。
サービスの登録
Startup
の ConfigureServices
で HogehogeDbContext
と HogehogeDataService
をサービスとして登録します。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MyFirstBlazorApp.Data;
namespace MyFirstBlazorApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<HogehogeDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("HogehogeConnection"),
providerOptions => providerOptions.CommandTimeout(120)));
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<HogehogeDataService>();
}
// ~後略~
}
}
DbContext
を AddDbContext
で登録する際に options
(DbContextOptionsBuilder
) の UseSqlServer
を呼び出して設定ファイルの接続文字列を読み込ませることで、この接続情報を使ったインスタンスが生成されるようになります。
AddDbContext
の第2引数を省略すると有効期限 (Lifetime) は Scoped
で登録されます。有効期限の詳細は サービスの有効期限 - ASP.NET Core での依存関係の挿入 を参照してください。
データサービス HogehogeDataService
も AddScoped
メソッドでサービスとして登録しておきます。
以上で HogehogeDataService
を利用する準備が整いました。
ビュー側で利用する
テンプレートから作成した状態では Pages/FetchData.razor
では WeatherForecastService
が使用されているので、 HogehogeDataService
を利用するように変更します。
@page "/fetchdata"
@using MyFirstBlazorApp.Data
@inject HogehogeDataService HogehogeData
<h1>Hogehoge Users</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (users == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
@foreach (var user in users)
{
<tr>
<td>@user.Id</td>
<td>@user.Name</td>
</tr>
}
</tbody>
</table>
}
@code {
List<User> users;
protected override async Task OnInitializedAsync()
{
users = await HogehogeData.GetUsersAsync();
}
}
この状態で F5 (実行) すれば Fetch data ページでユーザーの一覧が表示されるはずです。
次の記事
次回はパスワードなどの秘密情報をリポジトリ外に保存する Secret Manager を使ってみます。