👾

Jetbrain Riderで始めるASP.Net開発~DB接続からマイグレーションまで編~

2023/08/14に公開

前書き

https://zenn.dev/akty/articles/c44c743c022b2d
こちらの続きとなります

準備

PackageのDL

まずは必要なパッケージをDLしましょう

まずはNugetPackegeを開き

↑画像のパッケージを取得してください

Pluginの取得

EntityFrameworkCoreUIというプライグインをDLしておいてください
※これがないとマイグレーションできない。詳しくはこちら

コードの追加

UserContext

こちらのコードを追加してください

using Microsoft.EntityFrameworkCore;

namespace Proj.Models;

public class UserContext : DbContext
{
    public UserContext(DbContextOptions<UserContext> options)
        : base(options)
    {
    }

    public DbSet<User> Users { get; set; }
}

public class User
{
    public long Id { get; set; }
    public string Name { get; set; }
}

UserクラスはDBのレコードとなります
UserContextクラスがDBを参照するためのDIとなる想定です

UserController

こちらのコードを追加してください

using Proj.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace app.Controllers;

[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly UserContext _context;

    public UserController(UserContext context)
    {
        _context = context;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<User>>> GetUserDatas()
    {
        return await _context.Users.ToListAsync();
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<User>> GetUser(long id)
    {
        var testData = await _context.Users.FindAsync(id);

        if (testData == null)
        {
            return NotFound();
        }

        return testData;
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> PutUser(long id, User userData)
    {
        if (id != userData.Id)
        {
            return BadRequest();
        }

        _context.Entry(userData).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!UserExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return NoContent();
    }

    [HttpPost]
    public async Task<ActionResult<User>> PostUser(User userData)
    {
        _context.Users.Add(userData);
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetUser", new { id = userData.Id }, userData);
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteUser(long id)
    {
        var testData = await _context.Users.FindAsync(id);
        if (testData == null)
        {
            return NotFound();
        }

        _context.Users.Remove(testData);
        await _context.SaveChangesAsync();

        return NoContent();
    }

    private bool UserExists(long id)
    {
        return _context.Users.Any(e => e.Id == id);
    }
}

こちらがAPIの定義となります

DbContext

単純に切り分けていますが後述するProgram.csに直接書いてしまっても問題ありません

using Microsoft.EntityFrameworkCore;
using Proj.Models;

public static class DbContextBuilder
{
    public static void Setup(WebApplicationBuilder builder)
    {
        //サーバーのデータ定義
        var connectionString = "server=localhost;user=root;port=3306;password=password;database=hoge;";
        var serverVersion = new MySqlServerVersion(new Version(8, 0, 27));
        //サーバーのコンテキストを追加
        builder.Services.AddDbContext<UserContext>(
            dbContextOptions => dbContextOptions
                .UseMySql(connectionString, serverVersion)                
                .LogTo(Console.WriteLine, LogLevel.Information)
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors()
        );
    }
}

サーバーへの接続情報がこちらとなります

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

//DbContextの設定
DbContextBuilder.Setup(builder);

var app = builder.Build();

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

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

基本的にはデフォルトのコードにDbContextBuilderを追加しただけとなります
MySQLの接続設定を追加しただけですね

DB接続

DBのDocker起動

自分がDockerfileです

version : '3'
services:
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: foo
      TZ: "Asia/Tokyo"
    ports:
      - 3306:3306

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080

#  api:
#    image: dotnetasp
#    container_name: docker_dotonetas_api
#    build:
#      context: .
#    ports:
#      - 5000:80

まだ使いませんが、一応コンパイルしたASP.Netのコンテナの定義も書いてあります

docker-compose up

こちらでDBを起動しておきましょう

riderでのDB接続


MySQLのDataSourceを選択します

雑に接続設定をします

今回はrootUserでアクセスします
接続確認は画像下部のTestConnectionを押して確認しましょう

では、DbContextクラスを定義した際に書いたここを思い出してみましょう

var connectionString = "server=localhost;user=root;port=3306;password=password;database=hoge;";

設定情報となります
passwordが出ちゃってますが気にせず。。。
database指定でhogeが選択されているので、hogeを作成しましょう

riderでDB接続できていれば、コマンド入力と左上の再生ボタンを押すだけで実行できます

マイグレーション


Solutionからプロジェクトファイルを右クリックしてください

こちらのメニューからマイグレーション作成のメニューが開けます

最初なので必要なものはすべて選択されてます

OKを押すと↓のようにマイグレート用のスクリプトができます

また先ほどのメニューからUpdateDatabaseを選択してください

メニューのOKを押してマイグレートを実行しましょう

実行するとhogeにUsersが追加されていることが確認できます

動作確認


ここのメニューからHttpを選んでくださいそしてそして「Run」を押すとSwaggerが起動します

こちらでAPIの動作確認やクライアント側での呼び出し確認が可能となりました

以上となります

Discussion