ページ

2011年1月9日日曜日

.NET勉強中:ADO.NET Entity Framework入門 第1回 最新DBアクセス・フレームワークの基本的な考え方


第1回 最新DBアクセス・フレームワークの基本的な考え方


概念モデルがDBに依存してしまっているように思えますが。アプリケーション視点というより、かなり論理モデルに近いレベルになってしまっているように思えます。DBのエキスパートはDBの論理モデルでアプリケーションを検討してしまうことがあります。この記事もそういう影響下にあるのかもしれません。

アプリケーションを(DBとは独立に)考えるのであればこの段階でDBの概念モデルが出てくること自体、考え方がDBに依存してしまっている証拠です。本来であればここはDBとは無関係な、オブジェクトモデリング使って欲しいところですね。でもって、このオブジェクトモデルをDBにマッピングするためにO/Rマップを行ないたいところですが、知っている限りではそのような高機能のO/Rマッパーは存在してません。このレベルのインピーダンスミスマッチは手作業で解決するしかないようです。

オブジェクトモデル/RDBモデルのインピーダンスミスマッチについてはこの記事よりも、関連情報を探していて見つけたこちらの「O/R インピーダンスミスマッチ」の方が本質を突いていると思います。オブジェクトモデリングから見たO/Rマップ(LINQ向け、ただし手動)の話も出ています。RDB概念モデルからではなく、このようにオブジェクトモデルからスタートした方がインピーダンスミスマッチがより理解し易くなります(が、これも私にとってはRDBモデルよりオブジェクトモデルの方が馴染みが深い所為だからでしょう)。


当初は「別のもの」といいながら、O/R Mapping ベースで説明が進んでいますね。

概念モデリングについて、DBに慣れた人はいきなり論理モデルから、とかいっていますが、それ以前に考え方自体がRDBベースになってしまっている点については無自覚のようです。人間だれしも使い慣れた考え方で設計してしまいますから。RDB一筋の人は、本当になんでもRDBとSQLで考えてしまうようです。すごいというか(多段SQL平気で扱いますから)まぬけというか(通常コードの方がよほど簡単、高速に処理できるものでもSQL化してしまいます)、専門家だからといって変に信頼すると泣きを見ることになりますよ(実際そういう目に会いました)。

参考として最後に高機能なO/Rマッパーの話が書かれています。残念ながら私はそのような高機能O/Rマッパーを使ったことがないのですが、オブジェクト設計からRDBのレコードにまでマップ可能なO/Rマッパーがあるのなら使ってみたいですね。この記事では Entity Framework にそのレベルの機能があると示唆していますので、期待して読み続けるとしましょう。


実際に Entity Data Model を作成する解説です。VS2010で解説していますが、試してみるとVS2008 Express でも使えます。ただ、記事の先に出てきますが、VS2008では作成されたEDMを基にORmapすると名前の衝突が起きてしまうそうで、VS2010ではその部分が解決された、とのことです。VS2008には機能はあるものの出来は今一つだったのでしょう。そもそも使っている人があまり居なかったのかもしれません(出来が悪いから使われない、使われないから出来が悪いまま)。まあ、MSの場合、きちんと使えるようになるのはメジャーリリース3回目から、という法則がありますので、こんなものでしょう。

しかしEDMモデラー、低速マシンで使っていると腹が立ってきます。あまりにも動きが鈍い。というか、これが気持よく使える環境となるとどのぐらいのマシンを想定しているのでしょうか?自前でオブジェクト定義したくなってきます。結局、自前でORマップするほうが手っ取り早いのかもしれませんね。

注:後で判明したのですがVS2008のどこかが壊れていたようです。あまりにも操作への反応が悪すぎる(ファイル保存で1時間経っても完了しません)ので、再インストールしてみたら反応がよくなりました。

本ページの後半についてはVS2010で追加された機能で、VS2008では使えません。文字列データについて長さの制限ができないのは痛いですね。ですが、概念モデル設計では文字列の長さなぞは本来不要のはずです。VS2010でそれが追加されたということは自動ORマップの精度、あるいは機能性を向上させるためでしょう。

さて、VS2010を入れましたので、この部分から実際に試してみたいと思います。出来合いの人様のアプリでは面白く無いので、自前のアプリを設計してみるとしましょう。以下は手元のVS2010(Exp)で実行しながらのメモです。

プロジェクトの生成するところから違っています。VS2010Expressだからでしょうか、カテゴリとかはなく直接テンプレート一覧が出てきますね。私の方でもコンソールアプリでやってみましょう。コンソールアプリテンプレートから名前を付けてプロジェクトを生成しました。プログラムエントリ(Mainメソッド)を持ったクラスが用意されます。

ここで項目を追加。EDMモデリングのためには ADO.NET Entity Data Model を追加します(が、その下の ADO.NET EntityObject ジェネレータも気になります。後で調べてみましょう)。追加するとモデルを空から生成するか、既存DBから生成するかを聞いてきます。実は既にVS2008ベースで用意したDBが存在してはいますが、ここはVS2010のEDM機能を調べるものなので、あえて、空の状態から作っていきます。

追加によってEDMのデザイナ画面が表示されて、まずは、そのデザイナレベルでのプロパティ設定、オブジェクトの複数化をtrueにします。これは命名規則的にテーブルは複数形、オブジェクト(レコード)は単数形、を使うことが多いためですね。これはVS2008には無かった機能で、すごくマイナーな機能ですが、割合と有り難い機能でもあります(自動ツールって命名がいいかげんなものが多くて後になって困る事がありますよね)。

この後、ツールボックスからエンティティ、アソシエーション、継承関係、をD&Dしてデザインしていくわけですが、ここで再確認、EDMデザイナでデザインするものはあくまでDBの論理モデルですよね。結局のところ概念モデルから論理モデルへの展開はIDE外で(手動で)行なわれている前提ですね。このあたり記事のあたまに概念モデル云々が出てきていますが、デザイナー的にはそれは関係ない、ということになりますか。であればあえて概念モデルの話、出さなくてもよかったように思えますね。

後のほうで読むと、またMSのドキュメント(KB等)ではEDMでデザインしているものを概念モデルと称していますね。このあたりの用語の使い分け、結構いいかげんなのではないでしょうか。個人的にはEDMデザイナでやっていることが概念モデルとはとても思えないのですが、世間一般ではこのレベルを概念モデルというのでしょうかね。どうみても論理モデル展開したものをデザインしているようにしか見えないのですが。

さて気を取り直して作業継続です。二つの(DB)エンティティを用意します。一つはディレクトリ情報を保持するもの、もう一つはファイル情報を保持するもの、です。概念的に複数のファイル情報が一つのディレクトリ情報に関連付けられます(n:1)。追加したエンティティには自動割付のIDがデフォルトで用意されるようです。私の考えるDBデザイン的にもこれは必須ですので少し楽ができます。ID以外の属性は手動で追加ですね。

デザイナ上で属性(プロパティ)を追加する場合には3種類のプロパティ、スカラー、複合、ナビゲート、を選択する形式になっています。スカラー、複合は一般名称ですから判りますが、ナビゲーションプロパティってなんでしょう?ちょっと調べたらMSDNライブラリに記述がありました「ナビゲーション プロパティ (EDM)」。ただ、これVS2008用の説明なんですね。VS2010のものは見つかりませんでした。まあ、きっと同じものでしょう。ナビゲーションプロパティで指定されたもの(アソシエーションを示します)は、オブジェクトマップされた時にコレクションとしてマップされるそうで。これはある意味便利ですね。ただ、メモリ制約その他を考慮した場合に、そのマップが適切かどうかは別途検討する必要がありそうです。使うかどうかはまた後で検討することにしましょう。差し当たってはナビゲーションプロパティは無しで進めていきます。

ディレクトリ情報の方では、ディレクトリのフルパス名を保持します。ファイル情報の方では、ファイルが属しているディレクトリ(のID)、ベース名、サイズと日付、そして文字列形式でのハッシュ値、を保持します。EDM的にはディレクトリへのリンクは別途定義するものらしいのですが、そのあたりは無視してIDリンクも持たせておきます。


EDMモデルから論理モデルの自動生成です。VS2008ではどこまでできるのでしょうか。

最初にDB接続を作ります。他の実験でC:\TEMPにMDFファイルを作っているので、今回も同様にC:\TEMP下に作ります。なお、以前のトラブルでデフォルトのSQLサーバインスタンス名'SQLEXPRESS'が無効になっていますので、詳細設定でいちいちインスタンス名を変更しなければなりません。面倒です。

エンティティをDBにマップ(今回は自動生成)するのにVS2010ではエントリのコンテキストメニューから「モデルからデータベースを生成」、となっていますが、VS2008にはありませんね。ここで打ち止めでしょうか。VS2008にあるのは「データベースからモデルを更新」です。とりあえずこれを実行してみると、まあ、当然ですがエラーになります。名前からして、これは既存DBとのマッピングを行なうツールでしょうね。あ、最後まで読むとちゃんとそのところが記載されていました。

VS2010ではエンティティ定義からDB定義への展開(VS2008の逆方向)もできるようになっているそうです。やってみましょう。

とはいうもののDB接続だけは先に用意しておかなければならないようです。このあたりはまだ不完全ですね。どうせなら全部エンティティ側からできるようになっていればいいのに。メニューは「モデルからデータベースの生成」ですが、実際にはDBとの接続コンテキストおよびエンティティに対応したテーブルを作成します。最終的にはデータ定義(テーブル定義)のSQL文が生成されて確認用に表示されますので、そこで意図した通りのものができているかどうかチェックすべきです。というわけで結局SQLの知識が必須、SQL知らないでできるというものでは無いようです。どうにも中途半端さの漂うデザイナです。まあ、すべて自前で、よりは遥かに簡単ではありますので、それで良しとしましょう。

注:気持ち悪いことに、プロジェクトを前もって保存しておかないとデータ定義SQL文がテンポラリプロジェクトファイルから生成したことになりますね。先に保存して正しいソースがどこにあるかが判るようにしておくべきです。

さて、ここまでで、データ定義のSQL文が生成されますが、テーブルはまだ生成されていません。またDBへの接続文字列が App.config ファイルに記録されます。DBにテーブルを追加するにはデータ定義SQLを実行するのですが、記事では

メニューバーから[データ]-[Transact-SQL エディター]-[SQLの実行]を実行する

となっています。が、メニューバーの[データ]メニューにはそんな項目が出てきません。さあ、困った。ひょっとして、ちゃんと記載されていませんが、このあたりの機能は Expresss版ではサポートされていないとか。こういう解説記事書くような人は皆さん Ultimate版だったりしますからね。しょうがないので、DBエクスプローラからクエリーを開いて、CREATE TABLE 文をコピペして実行させました。本当にこうするしかないのであれば、EDM機能、少なくともDBテーブル生成機能は、Express版ユーザには役立たず、ということになります。こんな面倒掛けるよりDBを先に定義しておいてから、アクセスオブジェクト作るほうが楽そうです。

なお、コピペ実行で作ったテーブルですが、それを元にEDMを追加すると、主キーが無いという警告が出ます。どうも、DBをちゃんと(手動で)定義してからEDMでマップしてやるのが、少なくともExpress版では、無難なようです。

0 件のコメント:

コメントを投稿