DbContext 利用時の接続文字列の指定とデータベース更新の制御

DbContext ではコンテキストを利用しただけで、LocalDB (あるいは SQL Express) に自動的に接続してデータベースを作成する・・・

これがコードファースト・・・

接続先のデータベースは自動的に作成される・・・

何でも自動化でありがたい、といいたいところですが、開発者一人で作ってる、個人的なデータベースならいざ知らず、 実際の運用時に自動的に都合の良いところにデータベースを作成したり、 必要に応じてカラムが追加されたり、削除されたり、とか、データベースに対してそんな自由な感じを望むことって、まずないですよね(苦笑)

DbContext を利用しても、ちゃんと接続先のデータベースを指定したり、カラムを勝手に追加しないように制御したりすることも可能です。

ここでは DbContext 利用時のデータベースの制御方法についてみていきましょう。

DbContext 利用時に接続文字列で指定したデータベースに接続する

接続先データベースを指定する接続文字列 (Connection strings) は通常、設定ファイル (*.config) の connectionStrings 要素に記述します。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add 
      name="MyConnection"
      providerName="System.Data.SqlClient"
      connectionString="Server=.\SQLEXPRESS;Database=MyDb1;Integrated Security=true;"
    />
</configuration>

ここでは SQL Server Express 内に作成した MyDb1 というデータベースを指定しています。DbContext で作るデータベースはここに作成したいとします。 接続文字列のキー名は "MyConnection" です。

この場合、DbContext にその接続文字列を渡すには、次のように DbContext を派生したクラス (ここでは MyDbContext) を作り、 そのコンストラクタで接続文字列を渡します。

using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;

namespace DBTest1 {

    class MyDbContext : DbContext {

        public MyDbContext()
            : base( "MyConnection" ) {
            Database.SetInitializer(
                new MigrateDatabaseToLatestVersion
                    <MyDbContext, MyDbConfiguration>() );
        }

        public DbSet<Customer> Customers { get; set; }
    }

    class MyDbConfiguration 
        : DbMigrationsConfiguration<MyDbContext> {
        public MyDbConfiguration() {
            AutomaticMigrationsEnabled = true;
        }
    }

    class Customer {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }

    class Program {
        static void Main( string[] args ) {

            using( var ctx = new MyDbContext() ) {
                ctx.Customers.Add( new Customer {
                    FirstName = "Ichiro",
                    LastName = "Suzuki",
                    Age = 30
                } );

                ctx.SaveChanges();

                foreach( var c in ctx.Customers ) {
                    Console.WriteLine( "{0}", c.FirstName );
                }
            }
        }
    }
}

データベースの初期化方法の指定 ~ 自動マイグレーションの有効化と無効化

MyDbContext のコンストラクタでは接続文字列を、ベースクラスのコンストラクタに渡すことの他に、 データベースの初期化方法及びマイグレーション方法を指定しています。

ここで EntityFramework の DbMigrationConfiguration クラスを継承した MyDbConfiguration クラスを定義しています。

MyDbConfiguration のコンストラクタで、AutomaticMigrationEnabled プロパティを true にすると、関連する DB エンティティにフィールドが追加された時に、 それに対応するデータベースフィールドが自動的に作成されます

逆にフィールドが削除された時には、予期せずしてデータを損失することを防ぐために自動的にはデータベースのカラムはドロップされません。

カラムを削除しても良い場合は次のように、AutomaticMigrationDataLossAllowed を true にセットすればカラムは自動的に削除されます。

    class MyDbConfiguration 
        : DbMigrationsConfiguration<MyDbContext> {
        public MyDbConfiguration() {
            AutomaticMigrationsEnabled = true;
            AutomaticMigrationDataLossAllowed = true;
        }
    }

データベースの管理を手動に行う

一度システムが運用に入った後には、データベースのスキーマが変わるような変更が自動に発生してほしくない場合も多いでしょう。

データベースのエンティティのフィールドが追加されたときにも、データベースのテーブルには手動でカラムを追加したい場合は次のように、 SetInitializer に null を渡します。

    class MyDbContext : DbContext {

        public MyDbContext()
            : base( "MyConnection" ) {
            Database.SetInitializer<MyDbContext>( null );
        }

        public DbSet<Customer> Customers { get; set; }
    }

これによって、データベースの自動マイグレーションの発生は起こりません。

DB エンティティにフィールドを追加した場合は、同名のカラムをデータベースに手動で追加すれば OK です。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説