4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

新しい.NETのスキャフォールディングを試してみる

Last updated at Posted at 2024-11-21

はじめに

これまでCLIで.NETプロジェクトを利用して新しいプロジェクトを作成することはできましたが、新しいdotnet scaffoldコマンドを利用して作成済みのプロジェクトにコントローラーや、パッケージの追加などが行えるようになりました。

Visual StudioやRiderといったIDEではなく、CLIベースで作業する人にはうれしい新機能ですね。あとは、チュートリアルやQiitaのようにドキュメントベースで説明を行う場合にも、文字ベースで説明できるのでうれしい機能かもしれません。

インストール

グローバルにインストールしてもよいのですが、お試しなのでローカルインストールで進めていきます。まずはプロジェクトとツールマニフェストを作って、dotnet-scaffoldサブコマンドをインストールします。

❯ dotnet new webapi -o SampleApp1
❯ cd SampleApp1
❯ dotnet new tool-manifest
テンプレート "dotnet ローカル ツール マニフェスト ファイル" が正常に作成されました。

❯ dotnet tool install Microsoft.dotnet-scaffold
次のコマンドを使用してこのディレクトリからツールを呼び出すことができます: 'dotnet tool run dotnet-scaffold' または 'dotnet dotnet-scaffold'。
ツール 'microsoft.dotnet-scaffold' (バージョン '9.0.0') が正常にインストールされました。マニフェスト ファイル C:\localrepo\tmp\.config\dotnet-tools.json にエントリが追加されました。

初めて dotnet scaffold を利用する場合はテレメトリの収集に関する注意書きが表示されるので、なにかキーを押してしばらく待ちます。テレメトリを収集してほしくない場合は、ツールのインストール前にDOTNET_SCAFFOLD_TELEMETRY_OPTOUTDOTNET_CLI_TELEMETRY_OPTOUT環境変数へtrue, 1, yesのいずれかを設定すればデータ収集は行われなくなるそうです。

❯ dotnet scaffold
Telemetry

dotnet-scaffold collects usage data in order to help us improve your experience. The data is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the
DOTNET_SCAFFOLD_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.

Read more about dotnet-scaffold telemetry: https://aka.ms/dotnet-scaffold/telemetry
Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry

Press any key to continue...


                                    Installing Microsoft.dotnet-scaffold-aspnet.
▰▰▱▱▱▱▱ Getting ready               Installing Microsoft.dotnet-scaffold-aspire.

スキャフォールディングを使ったEFCoreのCRUD操作を持つコントローラーの追加

dotnet scaffoldを引数無しで実行すると、利用可能なスキャフォールドの一覧が表示されます。

❯ dotnet scaffold
Steps
───────────────────────
 Scaffolding Category
───────────────────────


Pick a scaffolding category:

> API
  Aspire
  Blazor
  Identity
  MVC
  Razor Pages
  (Show All)

  Navigation
    Exit

後は、表示されたウィザードに従いメニューを選択したり、テキストを入力すると対象のファイルが作成されます。今回はEFCoreのCRUD操作を持つコントローラーを追加したいので、まずはモデルを追加します。モデルは純粋な.NETのクラスなのでScaffoldingの対象にはなっていたいため、VSCodeやOSからファイルを追加する必要がありそうです。

User.cs
using System.ComponentModel.DataAnnotations;

namespace SampleApp1.Models;

public class User
{
    public int Id { get; set; }
    
    [Required]
    [MaxLength(200)]
    public string Name { get; set; } = null!;
}

改めてdotnet scaffoldを実行して、コントローラーやデータコンテキストをスキャフォールドします。データベースにはMySQLを指定したいところですが、現時点では存在しないのでSQLiteを指定しました。

ControllerScaffolding.gif

スキャフォールドを実行するとこのあたりのファイルが作成されたり、更新されたりします。
image.png

Microsoft.EntityFrameworkCore.Toolsへの参照を忘れないのエラい。いつも新しいプロジェクトを作るとマイグレーション時に気づくことが多いので

SampleApp1.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
  </ItemGroup>

</Project>

接続文字列もDbContextに直書きでなく、appsettings.jsonに外だしされるのはGood。

appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
-  "AllowedHosts": "*"
+  "AllowedHosts": "*",
+  "ConnectionStrings": {
+    "AppDbContext": "Data Source=AppDbContext.db"
+  }
}

Program.csにはDbContextの初期化コードだけ追加されます。

Program.cs
+using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
+var connectionString = builder.Configuration.GetConnectionString("AppDbContext") ?? throw new InvalidOperationException("Connection string 'AppDbContext' not found.");
+
+builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlite(connectionString));

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

ちょっとだけ修正

残念ながらサービスの依存関係(AddControllers)や、ルーティングの追加(MapControllers)は行ってくれなかったので、追加で修正する必要があります。あと、テスト用に開発時はSwaggerを使いたいのでパッケージを追加します。

❯ dotnet add package NSwag.AspNetCore

使わなそうなMinimal API部分はがりっと消して、3行追加しました。

Program.cs
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("AppDbContext") ?? throw new InvalidOperationException("Connection string 'AppDbContext' not found.");

builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlite(connectionString));

// Add services to the container.
+builder.Services.AddControllers();

// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
+    app.UseSwaggerUi(settings => settings.DocumentPath = "openapi/v1.json");
}

app.UseAuthorization();

+app.MapControllers();

app.Run();

マイグレーションスクリプトを登録後、データベースに反映して、

❯ dotnet tool install dotnet-ef
❯ dotnet ef migrations add first
❯ dotnet ef database update

実行します。

❯ dotnet run

出ました。ローカルのSQLiteに対してCRUD操作ができることを確認できます。

image.png

おわりに

次の部分でいくつか気になるところがありますが、

  • プロジェクトのルート以外ではファイルを生成できないわりに、コントローラーがカレントに吐き出される
  • UserControllerと入れたのにControllerが小文字になってしまっている
  • コントローラーの利用に必要なサービスの依存関係(AddController)やルーティングの設定(MapControllers)が追加されない

これから拡充されていくと思うので期待します~

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?