検索
リンク
タグ
ASP.NET
.NET
ASP.NET MVC
F#
Azure
Visual Studio
ASP.NET Core
ライトニングトーク
Plone
Selenium
AJAX
C#
jQuery
ADO.NET Entity Framework
JavaScript
SQL Server
EFCore
LINQ
WebMatrix
Fizz-Buzz
カテゴリ
最新の記事
最新のコメント
記事ランキング
最新のトラックバック
以前の記事
2024年 02月 2024年 01月 2023年 12月 2023年 11月 2023年 10月 2023年 09月 2023年 08月 2023年 07月 2023年 06月 2023年 05月 2023年 04月 2023年 03月 2023年 02月 2023年 01月 2022年 12月 2022年 11月 2022年 10月 2022年 09月 2022年 08月 2022年 07月 2022年 06月 2022年 05月 2022年 04月 2022年 03月 2022年 02月 2022年 01月 2021年 12月 2021年 11月 2021年 10月 2021年 09月 2021年 08月 2021年 07月 2021年 06月 2021年 05月 2021年 04月 2021年 03月 2021年 02月 2021年 01月 2020年 12月 2020年 11月 2020年 10月 2020年 09月 2020年 08月 2020年 07月 2020年 06月 2020年 05月 2020年 04月 2020年 03月 2020年 02月 2020年 01月 2019年 12月 2019年 11月 2019年 10月 2019年 09月 2019年 08月 2019年 07月 2019年 06月 2019年 05月 2019年 04月 2019年 03月 2019年 02月 2019年 01月 2018年 12月 2018年 11月 2018年 10月 2018年 09月 2018年 08月 2018年 07月 2018年 06月 2018年 05月 2018年 04月 2018年 03月 2018年 02月 2018年 01月 2017年 12月 2017年 11月 2017年 10月 2017年 09月 2017年 08月 2017年 07月 2017年 06月 2017年 05月 2017年 04月 2017年 02月 2017年 01月 2016年 12月 2016年 11月 2016年 10月 2016年 09月 2016年 08月 2016年 07月 2016年 06月 2016年 05月 2016年 04月 2016年 03月 2016年 02月 2016年 01月 2015年 12月 2015年 11月 2015年 10月 2015年 09月 2015年 08月 2015年 07月 2015年 05月 2015年 04月 2015年 03月 2015年 02月 2015年 01月 2014年 12月 2014年 11月 2014年 10月 2014年 09月 2014年 08月 2014年 06月 2014年 04月 2014年 03月 2014年 02月 2014年 01月 2013年 12月 2013年 10月 2013年 09月 2013年 08月 2013年 07月 2013年 06月 2013年 05月 2013年 04月 2013年 03月 2013年 02月 2013年 01月 2012年 12月 2012年 11月 2012年 10月 2012年 09月 2012年 08月 2012年 07月 2012年 06月 2012年 05月 2012年 04月 2012年 03月 2012年 02月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 04月 2011年 03月 2011年 02月 2011年 01月 2010年 12月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 10月 2009年 09月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 |
2014年 11月 08日
C# などの .NET アプリケーションで、データベースの読み書きで活躍する「Entity Framwork」。
そして Entity Framework を利用したプログラミングにおいて手軽さを発揮するのが "Code First" と呼ばれるスタイルの手順だ。 すなわち、POCO (Plain Old CLR Object. フレームワークに依存したクラスやインターフェースを継承しない、"素の" 型のオブジェクト) として、データベース上はテーブルにマップされるモデルクラスを定義したら(例えば C# の場合、下記のとおり定義したとして)、 publci class User {Entity Framework が提供する DbSet クラスから派生させた "データベースコンテキスト" クラスを作成し、そのプロパティとして、データベース上のテーブルにマップされるコレクションを定義すればよい。 public class MyDb : DbContext {そしてアプリケーション構成ファイル ( ASP.NET Web アプリであれば、web.config ) に記載するデータベース接続文字列として、データベースコンテキストクラスと同名のエントリを設ければ準備は完了だ。 <connectionStrings>これで、この Webアプリを実行し、データベースへの読み書き = すなわち、MyDb オブジェクトの Users プロパティに対する読み書きが発生すると、
自分でデータベースを構築する必要がないのである。 また、Entity Framework による機械的な自動データベース構築なので、データベース構造と C# のコード上とでの齟齬などが発生しない。 もちろん、必ずしもこういったコーディング手順に縛られず、データベースのテーブル構造などは別途構築しておき、Entity Framework にはデータベースの作成は任せないことでも構わない。 とはいえ、規模が小さめのしかしデータベースに読み書きをする Web アプリを構築する場合は、Entity Framework にテーブル作成を任せるスタイルの方が気楽で便利だ。 マイグレーションさて、開発が進んだりするにつれ、データベース構造の変化、例えばモデルにおけるプロパティの追加などが発生するだろう。publci class User { で、このままビルドして再実行すると... Unhandled Exception: System.InvalidOperationException: The model backing the 'MyDb' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).という例外となってしまう。 詳細割愛するが、まぁ、これは、世の中には色々な需要・要件があるので一概にライブラリの挙動を固定で決めることができず、既定では、モデルの変更が発生した場合は例外を発生させる仕様となっているわけだ。 ということで、データベース構造の更新、すなわち、マイグレーションの方法を、コード上で Entity Framework に教えておけばお好みの方法で対応可能だ。 ということで、ネットで「Entity Framework migration」などのキーワードで検索すると、何やら PowerShell コマンドを、Visual Studio の Package Manager Console で駆使して、そうやってデータベース構造を更新せよ、という記事が見つかる。 それらの手順に則ってマイグレーションを実施すれば OK だ。 だがしかし待ってほしい。 データベースの新規構築だけは自動で、そこからの実装の進化にあたっては手動ですよ、というのでは折角の Code First スタイルも魅力半減ではないのか? 自動マイグレーションということで、Entity Framework のどのバージョンからかは覚えがないが、「自動マイグレーション」の仕組みが用意されている。(ver.4 にはなかった。ver.6 には後述する自動マイグレーション機能が搭載済み。詳しくはリリースノート探して読むべし。) まず、自動マイグレーションの動作をいろいろ制御・指定するための "構成" クラスを記述する。 手軽な方法は、対象の ASP.NET Web アプリのプロジェクトを Visual Studio で開いた状態で、Visual Studio の Package Manager Console で、以下のコマンドを実行すればよい。 PM> Enable-Migrations -EnableAutomaticMigrationsすると、そのプロジェクトに Migrations フォルダが作成され、その中に Cofiguration クラスが作成される。 なお、このような秘密の PowerShell 呪文を唱えなくても、手で普通に Configuration クラスを書き起こしても構わない。 Migrations フォルダに配置する必要もないし、クラス名が Configurayion である必要もない。 データベースコンテキストクラス ( ここまでの例でいうと MyDb クラス ) を型引数に指定した DbMigrationsConfiguration<T> クラスから派生したクラスを実装し、
public class Configuration :そして次に、こうして自動マイグレーションの動作を指定する構成クラスも準備できたので、ASP.NET Web アプリなら、Global.asax.cs の Application_Start や、OWIN ベースであれば StartUp クラスなどで、データベース初期化アルゴリズムとして、MigrateDatabaseToLatestVersion オブジェクトを渡せばOKだ。 Database.SetInitializer(MigrateDatabaseToLatestVersion クラスは2つの型引数をとるジェネリック型であり、第1型引数は、ほかのデータベース初期化アルゴリズムクラスと同様に、初期化対象のデータベースコンテキストクラスを指定するが、第2型引数に、先に実装した構成クラスを指定する。 以上でアプリを実行すると、すでにテーブルに格納されているレコードを消してしまうことなどなく、列が自動で追加されてデータベース構造が更新され、アプリが稼働するのだ。 列の追加だけでなく、テーブルの追加 ( すなわち、データベースコンテキストクラスにおける、DbSet<T> なプロパティの追加 ) も同じように、既存のデータを壊すことなく、自動でデータベース構造の更新が実施される。 もちろん、こうしてローカル開発環境で動作確認が済んだコードを、クラウド上の PaaS に配置し、アクセスすれば、ちゃんと本番環境でも同じようにデータベース構造の更新がなされる。 同様に、モデルクラスを追加すれば、対応するテーブルがデータベース上に作成 ( CREATE TABLE ) される。 増えた列に何が入るか?さて、こうして自動マイグレーションによって、自動で追加された列に、初期値として何が入るか、だが、デフォルト値的な何かが入っている。軽く試してみた感じでは以下のとおりだ。
string 型のプロパティ(列) を追加したときに、NULL 許容型ではなくて非許容型とし、初期値として空文字 ('') が設定されるようにしたい場合は、そのプロパティに Required 属性を付けるとよい。 プロパティやモデルクラスを削除したら?さらに、そうやたらとあることではないと思うが、モデルクラスのプロパティを、「やっぱり要らなかった!」ということでコード上から削除したとする。そうしてビルド・実行すると... Unhandld Exception: System.Data.Entity.Migrations.Infrastructure.AutomaticDataLossException: Automatic migration was not applied because it would result in data loss. Set AutomaticMigrationDataLossAllowed to 'true' on your DbMigrationsConfiguration to allow application of automatic migrations even if they might cause data loss. Alternately, use Update-Database with the '-Force' option, or scaffold an explicit migration. という例外になる。いちどデータベースに格納されたデータを喪失するようなデータベース構造の更新は、ここまでの実装での自動マイグレーション方式では、安全をとって、実行されないのだ。 列の削除やテーブルの削除など、データベースオブジェクトの削除も許可して自動マイグレーションを実施したい場合は、先に述べた Congiguration クラスのコンストラクタにて、AutomaticMigrationDataLossAllowed プロパティを true に設定するとよい。 public class Configuration :こうすると、モデルクラスから削除されたプロパティに該当する列が削除される。 同様に、モデルクラスを削除した場合は、該当するデータベース上のテーブルが削除 ( DROP TABLE ) される。 まとめ本記事の一連の流れを、コミット履歴として保存してあるサンプルコードを、下記で公開した。https://github.com/sample-by-jsakamoto/EF-AutoMigrations 以上のとおり、アプリ実行のたびに、手放しで、C# で書いたモデルクラスの構造にデータベースの構造もぴったり追従させることが可能だ。 規模が小さい Web アプリを、バージョンアップを重ねながら開発・リリースしていく場合は、本記事で紹介したような「完全に Entity Framework に自動でお任せ」という方式のほうがいいのではないか、という気がしている。 もちろんケースバイケースではあり、規模が小さければとはいえ、新バージョンをリリース直後、どうしても都合により、一時的に旧バージョンにアプリをロールバックさせた場合など、新バージョンでいちどは増やした列やテーブルが消えてしまうので、そういうルーズな事情が許されるアプリかどうかには依るだろう。 ここではこれ以上言及しないが、開発時は全自動で、データベース構造がじゅうぶん安定したら、自動マイグレーションを無効化してリリースとかの方法も取れることだろう。 以上、参考になれば幸いである。
by developer-adjust
| 2014-11-08 00:17
| .NET
|
Comments(0)
|
ファン申請 |
||