0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C#(ASP.NET Core webapi)でMySQLを使うぞ?

Last updated at Posted at 2024-11-16

目次

  1. はじめに
  2. 使用環境
  3. プロジェクトの作成
  4. 実装
  5. 実行
  6. 終わりに

とある日。。。

天井を見ながらこう思った。「あ~C#でMySQL使いてぇ~。」

というわけで

作っていこうと思う。対象者は、C#でMySQLをイジメたい人向けです。

環境

  • VSCode with C#(.NET) extension
  • .NET 8.0.11 SDK
  • Docker

プロジェクト作成

以下のコマンドでプロジェクトを作成する

E:\Project> dotnet new webapi -o DatabaseApi
E:\Project> cd DatabaseApi
E:\Project\DatabaseApi> dotnet new sln
E:\Project\DatabaseApi> dotnet sln add .

NuGetパッケージの追加

MySQLをC#上で使えるようにするため、パッケージを追加する

E:\Project\DatabaseApi> dotnet add package MySql.EntityFrameworkCore --version 8.0.8

書いていこう

テーブル操作を統一するために、リポジトリインターフェースを実装する
お好みに改造してかまわない

IRepository.cs
namespace DatabaseApi;

///<summary>
/// テーブル操作インターフェース
/// <p>
/// T - テーブルデータクラス
/// </p>
///</summary>
public interface IRepository<T> where T : class
{
    protected Task<T> CreateAsync(T newData);
    protected Task<T> UpdateAsync(T updatedData);
    protected Task<bool> DeleteAsync(T targetData);
}

データベース操作用の基底コンテキストクラスを作成する

BaseDbContext.cs
using Microsoft.EntityFrameworkCore;

namespace DatabaseApi;

public abstract partial class BaseDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        throw new NotImplementedException();
    }
}

データベース用のコンテキストクラスを作成する

ExampleDbContext.cs
#pragma warning disable CS8618
using Microsoft.EntityFrameworkCore;
using MySql.Data.MySqlClient;

namespace DatabaseApi;

public partial class ExampleDbContext() : BaseDbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connectionStr = new MySqlConnectionStringBuilder()
        {
            Server = "localhost",
            Port = 3306,
            UserID = "root",
            Password = "P@ssw0rd",
            Database = "Example"
        }.ToString();

        optionsBuilder.UseMySQL(connectionStr);
    }
}

テーブル用のデータオブジェクトクラスを追加する

Example_TableA.cs
using System.ComponentModel.DataAnnotations;

namespace DatabaseApi;

public class TableA
{
    [Key]
    public string Id {get; set;} = null!;

    public string Name {get; set;} = string.Empty;
    public string Birthday {get; set;} = string.Empty;
}

データベース用のコンテキストクラスにテーブルを追加する

ExampleDbContext.cs
#pragma warning disable CS8618
using Microsoft.EntityFrameworkCore;
using MySql.Data.MySqlClient;

namespace DatabaseApi;

public partial class ExampleDbContext() : BaseDbContext, IRepository<TableA>
{
    public DbSet<TableA> Users {get; private set;}

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        ...
    }

    public async Task<TableA> CreateAsync(TableA newData) { ... }
    public async Task<TableA> UpdateAsync(TableA updatedData) { ... }
    public async Task<TableA> DeleteAsync(TableA targetData) { ... }
}

同期関数でも大丈夫ですが、同時にいくつも処理を行う場合は非同期にしてください。

処理を追加する

ExampleDbContext.CreateAsync(T newData)
public async Task<TableA> CreateAsync(TableA newData)
{
    await Users.AddAsync(newData);
    await SaveChangesAsync();

    return newData;
}
ExampleDbContext.UpdateAsync(T updatedData)
public async Task<TableA> UpdateAsync(TableA updatedData)
{
    var target = await Users.FirstOrDefaultAsync(x => x.Id == updatedData.Id);

    if (target == null) throw new Exception("Target not found.");

    target.Name = updatedData.Name;
    target.Birthday = updatedData.Birthday;
    
    Users.Update(target);
    await SaveChangesAsync();

    return target;
}
ExampleDbContext.DeleteAsync(T targetData)
public async Task<TableA> DeleteAsync(TableA targetData)
{
    var target = await Users.FirstOrDefaultAsync(x => x.Id == targetData.Id);

    if (target == null) throw new Exception("Target not found.");

    try {
        Users.Remove(target);
        await SaveChangesAsync();
        return true;
    } catch {
        return false;
    }
}

webapiを書き換える

Program.cs
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton(new DatabaseApi.ExampleDbContext());
builder.Services.AddOpenApi();

var app = builder.Build();

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

app.UseHttpsRedirection();

app.MapGet("/get", async (DatabaseApi.ExampleDbContext db) =>
{
    return await db.Users.ToListAsync();
});

app.MapPost("/add", async (DatabaseApi.ExampleDbContext db) =>
{
    var newData = new DatabaseApi.TableA()
    {
        Id = "1",
        Name = "John",
        Birthday = DateTime.Now.ToString()
    };
    return await db.CreateAsync(newData);
});

app.MapPost("/update", async (DatabaseApi.ExampleDbContext db) =>
{
    var newData = new DatabaseApi.TableA()
    {
        Id = "1",
        Name = "Josh",
        Birthday = DateTime.Now.ToString()
    };
    return await db.UpdateAsync(newData);
});

app.MapDelete("/remove", async (DatabaseApi.ExampleDbContext db) =>
{
    var newData = new DatabaseApi.TableA()
    {
        Id = "1"
    };
    return await db.DeleteAsync(newData);
});

app.Run();

これで、一通りの処理を追加したのでこれで使えるはず。
、、、DB無くね?

DockerコンテナでMySQLを起動する

以下のファイルを、プロジェクトフォルダの.containerフォルダ(ないと思うので作ってください)に作成する

MySql.Dockerfile
FROM mysql:latest

# この書き方は望ましくない(非推奨)ので心配なら別の方法をググってください
ENV TZ="Asia/Tokyo"
ENV MYSQL_ROOT_PASSWORD="P@ssw0rd"
ENV MYSQL_DATABASE="Example"

EXPOSE 3306

COPY ./init.sql /docker-entrypoint-initdb.d
init.sql
USE Example;

CREATE TABLE IF NOT EXISTS Users (
    Id VARCHAR(255) NOT NULL PRIMARY KEY,
    Name VARCHAR(255) NOT NULL,
    Birthday VARCHAR(255)
);
E:\Project> docker build --pull --rm -f ".container\MySql.Dockerfile" -t mysql:latest ".container"
E:\Project> docker run -itd -p 3306:3306 mysql

成果物

VSCodeの拡張機能のThunder Clientなどを使用して以下の順序でリクエストを送信してみてください。すると、データを操作できていることがわかるはずです。もし、MySQLの設定が違ったり、データベースやテーブルの構造が異なったりする場合は、例外が発生します。

  1. http://localhost:5180/add
  2. http://localhost:5180/get
  3. http://localhost:5180/update
  4. http://localhost:5180/remove
  5. http://localhost:5180/get

ポート番号はプロジェクトの生成時に決定するため、人それぞれです。起動ログから確認できます。

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5180 <-------------- ココ!!
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: E:\Project\DatabaseApi

終わりに

これでC#を使って、MySQLを利用できるようになりましたね!
改善点や修正点などあれば、随時、編集リクエスト、コメントお待ちしております。

追記

このMySql.EntityFrameworkCoreでは、以下の脆弱性が警告として出ます。

warning NU1903: パッケージ 'Microsoft.Extensions.Caching.Memory' 8.0.0 に既知の 高 重大度の脆弱性があります
warning NU1903: パッケージ 'System.Text.Json' 8.0.4 に既知の 高 重大度の脆弱性があります
warning NU1903: パッケージ 'Microsoft.Extensions.Caching.Memory' 8.0.0 に既知の 高 重大度の脆弱性があります
warning NU1903: パッケージ 'System.Text.Json' 8.0.4 に既知の 高 重大度の脆弱性があります
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?