コードファースト自体は結構前に話題になったハズなのですが、ASP.NET MVC 6 でデータベースに接続する場合にはなんだかよくわからなかったので再調査。いやいや、データベースから POCO を作ることはあまり重要ではなくて、ASP.NET MVC 6 自体なんだけど…まあ、EF(Entity Framework)が扱えたほうがいいので、ちょっときちんと手順を追ってみる。
チュートリアル的にはいろいろあって、
- Building ASP.NET MVC 6 & Entity Framework 7 application using ASP.NET 5 RC
- ASP.NET5 MVC6 Entity Framework 7 を使って Database First する – BEACHSIDE BLOG
を使って手早く済ますのもよいし、Getting started with ASP.NET MVC 6 ? ASP.NET MVC documentation にチュートリアルがあるので、それに沿って進めてみる。急がば廻れというスタイルです。github のほうは、ちまちま作っている途中らしいので抜けもあるけど、Building your first MVC 6 application からの一連の操作はひと通りできているようです。英語だけど、画面キャプチャが貼ってあるので分かりやすいはずです。
本来やりたいことは
本来やりたいことは、テンプレートを使わないシンプルな ASP.NET MVC を作りたいのだけど、実はなにやら設定がややこしい。一度、Empty のテンプレートから作ってみたもののうまく DB に接続できなかったので、これは後で調べてみる。ポイントとしては、
- project.json に必要な dependencies を追加する。
- ApplicationDbContext クラスを用意する。
- POJO な Model クラスから dnx ef を使ってデータベースを作成する。
するらしい。後で手順を追いなおしてみる。
ASP.NET MVC 6 の Web Application テンプレートを使う
project.json の設定と ApplicationDbContext クラスがややこしいので、Getting started with ASP.NET MVC 6 に従って、テンプレートをそのまま使う。
あれこれ無駄なページができるのだけど仕方がない。最終的には Empty から作れるようにする。
POJO な Model クラスを作る
Adding a controller と Adding a view はチュートリアル的に流せば ok。ここで必要なのは、Adding a model になる。
手順通り Models/Movie クラスを作る。このあとスキャフォールディングを使って、Movie クラスに対応するコントローラとビューを自動作成する。
「追加」→「コントローラ」を選択して「Entity Frameworkを利用したビューがある…」を選択する。
対象となるモデルクラス(Movieクラス)を選択して、データコンテキストでは「ApplicationDbContext」を選ぶ
ApplicationDbContext はローカルPCにデータベースを作る方式で、もともと ASP.NET MVC 6 の Web Application に入っているものでユーザー認証とかに使っている。だから、自前で Empty プロジェクトから作るときは、ApplicationDbContext クラスと ApplicationDbContext クラスあたりを自前で作る必要がある(と思う)。
データベースの設定自体は、Startup.cs の ConfigureServices メソッド内に書かれていて、
1 2 3 4 5 6 7 8 9 | // Add framework services. services.AddEntityFramework() .AddSqlServer() .AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration[ "Data:DefaultConnection:ConnectionString" ])); services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); |
なところで DI 化されている。配布を考えると project.json にあったほうがいいのだが、試験的に使うのであれば直書きしてもいいと思う。
dnx コマンドで Entity Framework を作る
EF を使ったほうが LINQ が使えるようになる(そのためにわざわざコードファーストしている)ので、EF に対応させるのだがデザインでやるのではなくコマンドラインから実行する。ここの部分、最終的に DB から各テーブルを読み込んでという形になるのかコマンドラインのままなのかはわからないけども、Linux 上で ASP.NET MVC + EF + MySQL という組み合わせを考えたときにはコマンドラインでできたほうがよい。この手順は Use data migrations to create the database あたりから書いてある。マイグレーション(migrations)というスタイルで、EF クラスと DB のテーブルとを相互に反映させる仕組みになる。あれこれ書いてあるけど、コマンドラインで project.json のあるフォルダを開けばよい。
1 2 3 | dnu restore dnx ef migrations add Initial dnx ef database update |
dnu や dnx と打ったときにコマンドが見つからないと言われたときには、パスなどを設定するために
1 | dnvm upgrade |
するのだが、そもそも dnvm 自体がないといわれるときには、c:¥users¥ユーザ名¥.dnx¥bin にある。このあたりの手順は Installing ASP.NET 5 On Windows にある。Mac 版、Linux 版もあるのでインストール時に一度やっておけばいいだろう。
dnvm use 1.0.0-rc1-update1 -p を実行していないのは、dnvm upgrade したときのバージョンをそのまま使うからだ。
そんな訳で、うまく DB が作成されるとデバッグ実行ができるようになる。Create New でデータ登録をしてリストを表示させることも可能。
ローカルデータベースは何処にあるのか
できあがった ASP.NET MVC のサンプルを動かすとデータが保持されているようなので、どこかにデータベースがあるはずだ。MVC 5 の場合は、App_Data の中にローカルデータベースがあってそれを参照していたのだが、MVC 6 の場合にはそれがない。
何処にあるのだろうかと調べると Setup.cs の
1 2 3 4 | services.AddEntityFramework() .AddSqlServer() .AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration[ "Data:DefaultConnection:ConnectionString" ])); |
から、設定の Data:DefaultConnection:ConnectionString から接続文字列を読み取っているらしいことが分かる。
そこで applications.json という設定ファイルらしくものを覗くと
1 2 3 4 5 | "Data" : { "DefaultConnection" : { "ConnectionString" : "Server=(localdb)mssqllocaldb;Database=aspnet5-CodeFirst2-848a6bc9-9651-4b68-a5db-8b56f15a8be0;Trusted_Connection=True;MultipleActiveResultSets=true" } }, |
と書いてある。なんか接続文字列っぽくて、スキーマ名が 「mssqllocaldb」になっている。Working with SQL Server LocalDB にも書いてある。試しに SSMS(Sql Server Management Studio)を使って (localdb)mssqllocaldb を開いてみると、うまく接続できた上にそれらしいデータベースができていることが分かる。
データベースのプロパティを見れば、保存場所のわかる。
どうやら、c:usersmasuda の直下に置かれている。ああ、確かに豪快に Cドライブに置かれていることが分かります。まあ、これだとユーザー領域とか Cドライブを圧迫しちゃうよねという感じなので、これは別途データベース接続文字列を書き換えて元の SQL Server などに移せばよいでしょう。
これがコードファーストなので、コードからデータベースを生成する方法。だが、普通は既存のデータベースを使って EF なクラスを作るような CakePHP の Bake のような方法をとると思うので、これも後で試してみる。
ノーム・チョムスキーとコードファーストな余談
ふと Noam Chomsky: Bernie Sanders has the best policies な記事にあたって、チョムスキーが87歳で健在なことを知る。チョムスキーといえば言語学者で人工知能絡みで対話型の形態素解析とかで出てくるんだけど(最近では人工知能というと自動運転とか深層学習とかになっているので「言語」から離れているが)「哲学者」というよりもレッキとした科学者だ。言語の発生から扱い方はウンベルト・エーコの「ウンベルト・エーコの文体練習」を合わせて読むといい。いちだいブームになった「薔薇の名前」や「フーコーの振り子」も読んでもいいかもしれない。「薔薇の名前」がマスコミ的にもブームになったのは、そういう余裕があった時代ではなかったのかなと思ったり。
で、言語学的に言えばプログラミング言語も「言語」のうちだろう。非常に限られた文法しか持たない(最終的には厳密なアセンブリに変換するという束縛があるので)し、限定的な使われ方しかしないから、普通の自然言語とは違った見方がされる。狭いプログラム言語の中で、C# という言語があって、SQLという言語がある。コードファーストってのは、C# のコードの言語を、SQL という言語(正確にはデータベースの世界)に変換することだ。それを「テクスト」と言い直せば、C# が持つテクストと SQL が持つテクストを結び合わせて同じコンテクストで語ろうという話だ。翻訳の世界と同じになる。当然、日本語と英語のように、というよりも日本国内でも東北弁と鹿児島弁の違いのように単純な変換だけでは済まない。片方のテクスト上で語られるものは、片方のテクストの一語としては対応するものがない。しかし、とあるテクストが全体を網羅を持つという前提条件を付ければ、別のテクストはもうひとつのテクストに対して語数の違いはあるかもしれないが正確に変換できることになる。2つのテクストが存在する空間が、完全に重なりあっていないのであれば変換しえないものが出てくる。これがコードファーストとデータベースファーストとO/Rマッピングのインピーダンスミスマッチだったり、それぞれの違和感だったりする。ただし、「完全に一致する」ことを捨て去ってしまい、ある程度の共有領域を多くするという方針にすれば言語同士の変換は比較的楽になる。
このあたり、Scratch をはじめとする教育用言語も同じだよなーと。「教育用」という縛りを設けるのか、プログラミングをする思考に対する完全性を重視するのか(いわゆる道具立て)というところで、そこに「子どもだから」というプログラム言語的な欠損を最初に認めて作ってしまうと、そもそもが「教育」→「プログラミングができる」の達成すら危うくなってしまうのではないかなーと思ったりもする。だら、あくまで「プログラミング的な思考を養う」のほうがよいのかなと。
教育はさておき、現実的なところで言語で伝えることの限界と、その厳密性を突き詰めていくと、修辞法やら過去の習慣やら小学校での教育やらを含めて、相手とのずれとそれを許容する現実がある。それと同時に、許容できない現実もあることを認める…というか許容しなくても良いというのがある。なんというか、自分だけを中心にして世界が廻っているような人が権力を持つと(どういう経緯なのかよく知らんけど)あれこれ変なところに逝ってしまうんだなーと呆れたりする。まあ、現実的に呆れてもどうしようもないところに落ち着く前に、チョムスキーのように「いい加減にしろよ」ぐらいの釘は刺したほうがいいかもね。半藤一利によれば下り坂の30年間だったりするのだから。
参考になります!
一点、POJOは、plain old “Java” objectなのでは?
POCOと呼ぶんではないすかね?
https://ja.wikipedia.org/wiki/Plain_Old_CLR_Object
Thx です。typo か?と思ったのですが、自分の場合、改めて検索してみると Plane なオブジェクト(小さなオブジェクト)という意味で「POJO」を使ったり「POCO」をようで…どちらも同じ意味で使っています。オブジェクト指向の場合は Java に敬意を表して C# で「POJO」を使ったりしてますね。とはいえ、ここは「POCO」に直しておきます。