Entity Framework6で既存のデータベースからCode Firstでスキーマを作るには
2019-11-11
azblob://2022/11/11/eyecatch/2019-11-11-entity-framework-codefirst-import-schema-000.jpg

はじめに

前回の記事において、既存のデータベースを使って別のアプリを作る方法をお伝えしました。
前回使ったのは、モデルを作成する方法の中でもDatabase Firstと呼ばれる手法で、既存のデータベースをEF Designerを使用してリバースエンジニアする方法でした。
今回は、既存のデータベースからモデルを作成する方法のもう一つとして、Code Firstと呼ばれる方法を紹介していきます。

実装です!

前回と同じように、.Net Frameworkのコンソールアプリケーションでプロジェクトを立ち上げます。
そして、プロジェクト->新しい項目の追加 から・・・

ADO.NET Entity Data Modelを新規作成します。

そしてここで前回と違い、「データベースからCode First」を選択します。

あとは、前回の接続方法が残っていればその方法を使用し・・・

モデルに含めるデータベースオブジェクトとしてはテーブルを選択して完了ボタンを押します。

しばらくするとこのような3つのファイルが作成されます。

この方法で作成されるのはこれらの3つのファイルだけになります。
さて、それではデータベースに実際にアクセスしてみましょう。
前回のコードをほとんど変更せずにアクセスすることができます。

class Program
{
    static void Main(string[] args)
    {
        using (var context = new Model1())
        {
            Console.WriteLine("データを初期化しています");
            context.Models.RemoveRange(context.Models.ToList());
            context.SaveChanges();
            Console.WriteLine("データを追加しています");
            context.Models.Add(new Models { Column1 = "test", Column2 = 123 });
            context.Models.Add(new Models { Column1 = "test2", Column2 = 456 });
            context.SaveChanges();
            var datas = context.Models.ToList();
            Console.WriteLine("DB内に保存されているデータは:");
            datas.ForEach(d => Console.WriteLine($"{d.Column1}:{d.Column2}"));
            Console.ReadLine();
        }
    }
}

結果としてはこのようになるはずです。

データを初期化しています
データを追加しています
DB内に保存されているデータは:
test:123
test2:456

このようにして、アプリケーションからCode Firstでもほとんど同じようにデータベースにアクセスすることができるようになりました。

EF Designerを使った場合と何が違うの?

さて、今回は既存のデータベースからモデルを作成する方法としてCode Firstを紹介しましたが、前回のDatabase Firstにおける方法との間のやり方との違いとしてはモデル生成時にEF Designerを生成するかC#のコードを生成するかの違いしかありません。
これらのどちらを使うかによって何が変わるのか、あとどちらを個人的に推すかについて自分なりに解説してみたいと思います。

データベースの構造が変更された時の更新の方法が変わる!

私が把握している限りでは、これらの方法によって大きく変わる点はデータベースの構造が変化したときのアプリケーション側での変更の方法です。
例として、SSMSを利用してデータベースの構造を変更してみましょう。
SSMSをインストールしていない場合はダウンロードしてインストールしてください。
起動するとデータベースへの接続を求められるはずなので、これまで何度かコピー&ペーストしているデータベースのサーバー名をペーストして接続してください。


接続したサーバーのデータベース配下ののテーブルディレクトリ内からテーブルの情報を見たり変更したりできます。
今回はModelsのテーブルの構造(デザイン)を変更したいので、右クリックしてデザインを選択します。

すると、現在のそのテーブルのスキーマが表示されるので、Column2のデータ型をColumn1と同じnvchar(MAX)型(C#でいうところのstring型)に変更してみましょう。


ここを変更したらそのスキーマの変更をセーブしたいのですが、それにはひと手間必要です。
メニューバーのツール->オプションを開きます。

そして、メニュー内「デザイナー」から、「テーブルの再作成を必要とする変更を保存できないようにする」というチェックを外して、OKを押します。

これをしないとスキーマの変更の保存ができないため、注意してください。
また、これをした場合はした場合で、業務中にうっかりデータベース構造を変更して保存したりしてデータベースを壊す事態が起きる恐れがあるので、普段は付けておくようにするのをお勧めします。

スキーマのセーブができたらアプリケーションの開発に戻りましょう。
現在の状態でCode Firstでアプリケーションを作った場合、Database Firstでアプリケーションを作った場合はどちらもこのようなエラーが起きるはずです。

これはアプリケーションのEntity Frameworkがデータベースの構造が変わったために間違ったスキーマでデータベースにアクセスしようとするために起きます。
なので、両方のプロジェクトでスキーマの変更を行いましょう。

Database Firstの場合

Database Firstでスキーマの変更を行うには、まずソリューションエクスプローラーからModel1.edmxを選択します。
そして、まずは変更した既存のModelsを削除します。

その後、何もない場所を右クリックして「データベースからモデルを更新」を選択します。

すると更新ウィザードが立ち上がるので、追加するものとしてテーブルにチェックを入れ、完了をクリックします。
これで、スキーマの更新は完了です。

最後に、実装のコードをスキーマの変更に合わせて変更しましょう。
Column2の値がstring型になったので、そのように変更します。

class Program
{
    static void Main(string[] args)
    {
        using (var context = new Entities())
        {
            Console.WriteLine("データを初期化しています");
            context.Models.RemoveRange(context.Models.ToList());
            context.SaveChanges();
            Console.WriteLine("データを追加しています");
            context.Models.Add(new Models { Column1 = "test", Column2 = "123" });
            context.Models.Add(new Models { Column1 = "test2", Column2 = "456" });
            context.SaveChanges();
            var datas = context.Models.ToList();
            Console.WriteLine("DB内に保存されているデータは:");
            datas.ForEach(d => Console.WriteLine($"{d.Column1}:{d.Column2}"));
            Console.ReadLine();
        }
    }
}

これで更新に係る作業はすべて完了になります。
動かなかったアプリケーションはこれで再びエラーなく動作するようになったはずです。

Code Firstの場合

Code Firstの場合は、このような一部分だけ更新する方法を取ることができません。
なので、生成されているファイルを微調整するか、一旦作成されたスキーマを全部削除してモデルを作り直す必要があります。

おわりに

今回は、Entity Frameworkを使って既存のデータベースにアクセスしてスキーマを取得する方法として、Code Firstを紹介しました。
また、この方法と前回のDatabase Firstの間ではデータベースの構造変更時の対処法が違うことを解説しました。
最後に、これらのどちらをどのようなときに強いようするべきかについて少し持論を述べたいと思います。
他の意見等あれば、そちらを採用してもらっても構いませんし、コメントを頂ければ私とコメントを見たほかの方の知見が広がりますので、よろしくお願いします。
さて、Code Firstでモデルを作成した場合、作成されるファイルはDatabase Firstで作成した場合より少なく済みます。
しかし、データベースの構造に変化があった場合、作成したスキーマを全て再作成する手間がかかります。
新しく作成したものが以前の形と本当に同じなのかチェックする手間が増えてしまいます。
一方でDatabase Firstの場合はモデル更新の機能があるので、それを利用することで変更の範囲を押さえることができます。
これらのことを考えると、特にデータベースの構造の変化が多い場合は、Database Firstの方法で開発するのがよさそうに感じます。
一方で、データベースの構造がほぼほぼ決まっていて変更の予定がない場合や、あるいは全消ししてスキーマを作り直すことになっても全体の規模がそれほど大きくない場合などには、よりファイルがコンパクトにまとまるCode Firstの方法を使うのが適しているのではないでしょうか。