bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. [C#] マイグレーションでビューや関数を管理する

[C#] マイグレーションでビューや関数を管理する

Aug 12, 2026 C# , .NET , Entity Framework Core bucket-sort

前回は、DbContext に共通ルールを集約する方法を見ました。

今回は、マイグレーションでテーブル以外のデータベースオブジェクトを管理します。

EF Core のマイグレーションというと、テーブル作成や列追加の印象が強いかもしれません。
しかし実務では、ビュー、関数、ストアドプロシージャ、インデックスなども一緒に管理したくなります。

そのような場合は、マイグレーションの中で SQL を実行します。

SQL を直接実行する

マイグレーションには、Up() と Down() があります。
Up() は変更を進める処理、Down() は変更を戻す処理です。

public partial class AddCarSummaryView : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql("""
            CREATE VIEW dbo.CarSummaries
            AS
            SELECT
                c.Id,
                c.Make,
                c.Color,
                c.PetName,
                COUNT(o.Id) AS OrderCount
            FROM dbo.Inventory AS c
            LEFT JOIN dbo.Orders AS o ON c.Id = o.CarId
            GROUP BY c.Id, c.Make, c.Color, c.PetName;
            """);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql("""
            DROP VIEW IF EXISTS dbo.CarSummaries;
            """);
    }
}

これで、マイグレーション適用時にビューが作成されます。
戻すときにはビューが削除されます。

作成前に削除する

開発中は、同じビューを作り直したいことがあります。
その場合、先に削除してから作ると再実行しやすくなります。

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.Sql("""
        DROP VIEW IF EXISTS dbo.CarSummaries;
        """);

    migrationBuilder.Sql("""
        CREATE VIEW dbo.CarSummaries
        AS
        SELECT
            c.Id,
            c.Make,
            c.Color,
            COUNT(o.Id) AS OrderCount
        FROM dbo.Inventory AS c
        LEFT JOIN dbo.Orders AS o ON c.Id = o.CarId
        GROUP BY c.Id, c.Make, c.Color;
        """);
}

ただし、本番環境では依存関係に注意が必要です。
ビューを一度削除すると、そのビューに依存する権限や別オブジェクトへ影響することがあります。

変更内容によっては、CREATE OR ALTER VIEW のような構文を使う方がよい場合もあります。

関数を作成する

データベース関数も同じように作れます。

public partial class AddCarDisplayNameFunction : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql("""
            CREATE OR ALTER FUNCTION dbo.GetCarDisplayName
            (
                @make nvarchar(50),
                @color nvarchar(50),
                @petName nvarchar(50)
            )
            RETURNS nvarchar(200)
            AS
            BEGIN
                RETURN @make + N' ' + @color + N' ' + @petName;
            END
            """);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql("""
            DROP FUNCTION IF EXISTS dbo.GetCarDisplayName;
            """);
    }
}

この関数は、前回見たように DbContext 側で C# メソッドと対応付けられます。

マイグレーションで関数を作り、DbContext で使えるようにする。
この 2 つをそろえることで、データベース側の処理をアプリケーションから安全に呼び出せます。

SQL をヘルパーへ分ける

マイグレーションに長い SQL を直接書くと、読みづらくなることがあります。
小さなヘルパーを用意すると整理できます。

public static class MigrationSql
{
    public static void CreateOrAlterCarSummaryView(
        this MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql("""
            CREATE OR ALTER VIEW dbo.CarSummaries
            AS
            SELECT
                c.Id,
                c.Make,
                c.Color,
                c.PetName,
                COUNT(o.Id) AS OrderCount
            FROM dbo.Inventory AS c
            LEFT JOIN dbo.Orders AS o ON c.Id = o.CarId
            GROUP BY c.Id, c.Make, c.Color, c.PetName;
            """);
    }

    public static void DropCarSummaryView(
        this MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql("""
            DROP VIEW IF EXISTS dbo.CarSummaries;
            """);
    }
}

マイグレーション側は短くなります。

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateOrAlterCarSummaryView();
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    migrationBuilder.DropCarSummaryView();
}

ただし、ヘルパー化には注意もあります。
過去のマイグレーションが、後から変更されたヘルパーの内容に影響される可能性があるためです。

履歴として固定したい SQL は、マイグレーション内に残した方が安全な場合もあります。

インデックスを追加する

インデックスは EF Core の API でも作れます。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Car>()
        .HasIndex(car => new { car.Make, car.Color });
}

マイグレーションには、次のようなコードが生成されます。

migrationBuilder.CreateIndex(
    name: "IX_Inventory_Make_Color",
    table: "Inventory",
    columns: new[] { "Make", "Color" });

データの検索条件が明確なら、インデックスは性能に大きく影響します。
ただし、追加しすぎると書き込みが重くなります。

問い合わせの実行計画や実際のデータ量を見ながら、必要なものを追加していきます。

適用前に SQL を確認する

マイグレーションを本番に適用する前に、SQL スクリプトを生成して確認できます。

dotnet ef migrations script

特定の範囲だけを出力することもできます。

dotnet ef migrations script PreviousMigration CurrentMigration

運用環境では、アプリケーションから自動適用するより、生成された SQL をレビューしてから適用する方が安心な場合があります。

特に注意したいのは、次のような変更です。

  • 列の削除
  • 型の変更
  • 既存データに合わない制約追加
  • 大きなテーブルへのインデックス追加
  • ビューや関数の削除

マイグレーションは便利ですが、データベースへの変更であることに変わりはありません。

Down を書く意味

Down() は、変更を戻すための処理です。
開発中にはよく使います。

dotnet ef database update PreviousMigration

ただし、本番環境で安易に戻せるとは限りません。
列を削除した後に戻しても、消えたデータは復元されません。

Down() は「完全な復元保証」ではなく、「スキーマ変更を逆向きにできるようにする手段」と考える方が現実的です。

重要な変更では、バックアップ、移行スクリプト、リリース手順を合わせて考えます。

この記事のまとめ

EF Core のマイグレーションでは、テーブルだけでなく、ビュー、関数、インデックスなども管理できます。

migrationBuilder.Sql() を使えば自由度は高くなります。
その分、データベース固有の構文、依存関係、戻し方、運用手順も意識する必要があります。

データアクセス層を育てるということは、C# のコードだけでなく、データベース側のオブジェクトも同じ流れで管理できるようにすることです。

次回は、履歴テーブルを扱うリポジトリを作り、過去の状態を問い合わせる方法を見ていきます。

C# .NET Entity Framework Core Migration SQL Server データベース設計
← [C#] DbContext に共通ルールを集約する [C#] EF Core で履歴テーブル対応のリポジトリを作る →

Related Posts

  • [C#] EF Core で履歴テーブル対応のリポジトリを作る Aug 13, 2026
  • [C#] EF Core で既存データベースからモデルを作る Aug 9, 2026
  • [C#] EF Core でデータベースの準備と初期データを扱う Aug 8, 2026
  • [C#] EF Core のコマンドライン操作とマイグレーションを理解する Jul 28, 2026

Table of Contents

  • SQL を直接実行する
  • 作成前に削除する
  • 関数を作成する
  • SQL をヘルパーへ分ける
  • インデックスを追加する
  • 適用前に SQL を確認する
  • Down を書く意味
  • この記事のまとめ

Recent Posts

  • [WPF] XAML の構文を理解する: 名前空間とキーワード Aug 23, 2026
  • [WPF] Window クラスを支える基底クラス Aug 22, 2026
  • [WPF] Window クラスの役割と上位クラス Aug 21, 2026
  • [WPF] Application クラスの役割 Aug 20, 2026
  • [WPF] WPF の主要アセンブリと名前空間 Aug 19, 2026

Categories

  • C#165
  • .NET164
  • AWS27
  • Entity Framework Core24
  • Laravel16
  • Linux15
  • MySQL9
  • Apache8
  • PHP8
  • Data Access6
  • DynamoDB6
  • セキュリティ6
  • Nginx5
  • WordPress4
  • インフラ4
  • テスト4
  • Hugo3
  • .NET Framework1
  • Aurora1
  • Diagnostics1

Tags

  • C#
  • .NET
  • Entity Framework Core
  • AWS
  • Laravel
  • コレクション
  • PHP
  • セキュリティ
  • MySQL
  • Linux
  • パフォーマンス
  • LINQ
  • WPF
  • Apache
  • SQL Server
  • System.Collections.Generic
  • デリゲート
  • リフレクション
  • ADO.NET
  • Code Snippet
  • DbContext
  • DynamoDB
  • NoSQL
  • PHP-FPM
  • RDS
  • System.Collections
  • Windows
  • メタデータ
  • メモリ管理
  • CIL
  • DoS
  • Nginx
  • WordPress
  • アセンブリ
  • ラムダ式
  • 監視
  • 設計
  • Amazon Linux 2023
  • Delegate
  • Docker
  • IDisposable
  • Ipset
  • Iptables
  • LINQ to Objects
  • Migration
  • OPCache
  • Pointer
  • Reflection
  • System.Collections.Specialized
  • Unsafe
Powered by Hugo & Explore Theme.