1
3

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#でmigrationを試みる

Last updated at Posted at 2025-09-06

作成するDBの設計図

ひとまずSampleということで、DriverID、DriverName、validと運送業のドライバの方々の情報を格納するDBを作成したいと思います。
データベースはSqlite3を使用します。

Driver Table

-- DriverID DriverName valid
Type INT TEXT BOOL
PK -- --
UQ -- --
DEFAULT -- -- false

環境

OS : Ubuntu 24.04.3 LTS
IDE : VSCode 1.103.2
dotnet : 8.0.119
DB : Sqlite3 3.45.1

migrationをするための事前リサーチ

今回migrationすなわちC#からDBへのコードベースの簡易アクセスを行うツールとして、EF Coreとよばれるフレームワークを使用します[2]。
おおよそのその使い方は以下のようなイメージです。

  1. 作成するテーブル名を持ったクラスを作成
  2. DbContextを継承したクラスを作成(DbSetでテーブルクラスの定義)
  3. DBの設定

また、その流れは以下の図のようになるはずです。

実装

まずはプロジェクトにPackageをインストールします。

$ dotnet add package Microsoft.EntityFrameworkCore.Sqlite
...
$ dotnet list package
...
> Microsoft.EntityFrameworkCore.Sqlite         9.0.8       9.0.8   
> Microsoft.EntityFrameworkCore.SqlServer      9.0.8       9.0.8   
> Microsoft.EntityFrameworkCore.Tools          9.0.8       9.0.8
...

ディレクトリTree

.
├── Migartion
│   ├── DbContexts.cs
│   └── Driver.cs
├── Migrations
├── Program.cs
...

Entityの設定

using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore;

namespace SampleAPI.Entities
{
    public class Driver
    {
        [Key]
        [Required]
        public int DriverID { get; set; }

        [MaxLength(40)]
        [Required]
        public required string DriverName { get; set; }


        [Required]
        public bool valid { get; set; } = false;
    }
}

以上私が今回作ろうとしているテーブルのEntityです。
「Primary Keyの制約があるくせしてRequiredとは何事か?」みたいなツッコミはあると思いますが、目をつむっていただきたいです。

また、

public bool valid { get; set; } = false;

で=false;としてますが、これはDEFAULT制約を課すことができます。

後述しますが、これではDefault制約を課すことができなかったため別のアプローチが必要です。

また、基本的にはMicrosoft.EntityFrameworkCoreで用いる変数にはプロパティを使用します。
特にセッターの制限などは今回は必要ないため、自動実装プロパティ(get;set;)で良いと思います。

DBContextの設定

先ほど作成したエンティティを用いてContextを作成します。
当方、ContextはデータベースCRUDなどに必要な情報を定義するものだと把握しておりますが、実際のところどうかはわかりません。

using System;
using Microsoft.EntityFrameworkCore;
using SampleAPI.Entities;

namespace SampleAPI.DbContexts
{
    public class DriverDbContext : DbContext
    {
        public DriverDbContext(DbContextOptions<DriverDbContext> options) : base(options) { }
        public DbSet<Driver> Driver{ get; set; }
    }
}

DBContextはMicrosoft.EntityFrameworkCore.DbContextを継承することで作成します。

public DbSet<Driver> Driver{ get; set; }

まず、以上のようにエンティティDriverをDriverプロパティとしてDriverDbContextクラスに定義しておきます。

public DriverDbContext(DbContextOptions<DriverDbContext> options) : base(options){}

そうして基底クラスのコンストラクタにoptionsインスタンスを投げることでDbContextを定義できました。

DBサービスの設定

上記で作成したDbContextを用いてMigrationできるようにProgram.csで記述していきます。

using Microsoft.EntityFrameworkCore;
using SampleAPI.DbContexts;
...
builder.Services.AddDbContext<DriverDbContext>(options =>
    options.UseSqlite("Data Source=driver.db"));
...

Migrationの実行

$ dotnet ef migrations add InitialCreate
> Build started...
> Build succeeded.
> Done. To undo this action, use 'ef migrations remove'
$ dotnet ef database update

Project.csが存在するDirectoryにおいて上記を実行してください。
以下のようにdbが作成されているのが見て取れます。

$ find *db
> driver.db

また、正しくDriverテーブルが作成されているのがわかります。

sqlite> .mode line
sqlite> select * from sqlite_master;
...
    type = table
    name = Driver
tbl_name = Driver
rootpage = 5
     sql = CREATE TABLE "Driver" (
    "DriverID" INTEGER NOT NULL CONSTRAINT "PK_Driver" PRIMARY KEY AUTOINCREMENT,
    "DriverName" TEXT NOT NULL,
    "valid" INTEGER NOT NULL
)
...

正しくないことに今気が付きました。
validのdefault制約はどこに行ったのでしょうかね。

Default制約の見直し

DbContent.csを参照しても=false;が記述してあるのを確認できました。
即ちDefault制約の課し方が恐らく間違っているのでしょう。

どうやらContextにおいてOnModelCreatingというものを使用すればDefault制約を付与できる(正しくは制約を書き換える)らしいです[3][4]。

//DbContexts.cs

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Driver>()
        .Property(d => d.Valid)
        .HasDefaultValue(false);
}

そうして再度Migrationを行うと

    type = table
    name = Driver
tbl_name = Driver
rootpage = 7
     sql = CREATE TABLE "Driver" (
    "DriverID" INTEGER NOT NULL CONSTRAINT "PK_Driver" PRIMARY KEY AUTOINCREMENT,
    "DriverName" TEXT NOT NULL,
    "valid" INTEGER NOT NULL DEFAULT 0
)

正しくテーブルが登録できていることがわかりました。

おわりに

そういえばSqliteにはBool型なかったですね(๑>؂<๑)

Sqlite←字面が完全にジュースのSprite

参考資料

[1]

[2]

[3] DbContext.OnModelCreating(ModelBuilder) メソッド

[4] 生成された値

1
3
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
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?