ページ

2011年8月11日木曜日

◆ADO.NET Entity Frameworkに入門してみる

連載:ADO.NET Entity Framework入門 - @ITを読んで試してみた。
実によくまとまっていて解りやすい記事だ。

この中で「自己追跡エンティティ」をSilverlightから使うサンプルが載っていて、ちょうどSilverlightをかじり始めたところなので試してみた。

解りやすい説明なので簡単に実装できると思ったのだが(サンプルコードも提供されているし)、さにあらず。
大いに嵌りまくった。
私のような下々のレベルで使うには結構大変なのかも。

とりあえず試行錯誤の結果を纏めておく。

記事を見ながら自分でもつくってみたのだが、どうにも思い通りの動きにならないのでまずはサンプルを動かしてみることにした。
サンプルは以下からダウンロードできる。
http://www.atmarkit.co.jp/fdotnet/ef4basic/ef4basic07/ef4basic_7_sample.zip

ダウンロードしたサンプルを開くといきなりエラーが幾つか表示される。
image

ちょっと暗い気持ちになりながら眺めると、なぜかC#のプロジェクトとVBのプロジェクトが混在している。
両方のサンプルを示したかったのかもしれないが、本文中でも特に触れられていないし素人はこれだけでも理由を特定するのに戸惑ってしまう。

とりあえずVBプロジェクトは必要ないので削除する。
するとエラーは消えたのでまずは実行してみる。

初期画面は表示されたが、「Load」ボタンを押すと以下のようなエラーが出る。
image
image

ちなみに、記事を見ながら自分で作ったプロジェクトも同じエラーが出ていた。
こんな単純なところでも結構悩んだのだが、Openというからには雰囲気的にDBの接続っぽい。
そもそも接続文字列はどこで定義しているのだろう。
素人の悲しさでDataプロジェクトのApp.Configに追加してみたりして・・・。

確かめていくと、WebプロジェクトのWeb.Configに接続文字列を見つけた。
う~、データソースが「XPS\SQLEXPRESS」なんてことになっているのね。
「.\SQLEXPRESS」にしておいて欲しいところだ。
こいつを修正して実行すると、データ表示・更新ともに上手く行った。

さて、ここで自分で作ったサンプルではうまくいかなかった更新処理を調べてみる。
自分で作ったサンプルでは「AddressBookSilverlightApp」プロジェクトのサービス参照で使われるEntityが自前で作ったEntityではなく自動生成されたEntityとなってしまう。
記事の説明では「AddressBookSilverlightApp」プロジェクト内に予め自作のEntityを追加しておけばそちらが参照されるとなっている。
そこで提供サンプルのサービス参照「AddressBookServiceReference」をオブジェクトブラウザで見てみる。

確かに自前のEntityが使われているのが確認できた。
image

なにが違うのか色々調べたが、さっぱり判らない。
ふと思いたち、提供サンプルのサービス参照の更新を行ってみた。
image

するとどうだろう、自前のEntityではなく自動生成のEntity使用に変更されてしまった。
image

駄目じゃん・・・・。

ん~、どうもこの提供サンプルはVBプロジェクトなどがエラーに成っていたことからしても、作って動作確認したそのものではなく、サンプル提供用に編集されたもののような気がする。

この状態で実行してテストすると、やはり更新機能は動作しない。
半分挫折しかけたが気を取り直して、巷にこの記事に対する反応などが無いか検索してみるも、この記事に対するリンクは結構あるのだが、実際試した見たよ的な話は見当たらない。

仕方が無いので、他に「自己追跡エンティティ」に対する記事がないか検索して10 行でズバリ !! 変更履歴管理を伴ったエンティティを使用した多層階層システムの構築 (セルフ トラッキング エンティティ) (C#)を見つけた。
これを見ると、Entity群は独立したプロジェクトとして分離して、データプロジェクトとクライアントプロジェクトの両方から参照設定するという方法が取られている。

ん~、ここらへんが肝なのだろうか、と思いながら「提供サンプルを修正してみる」
しかし、これもまた色々と試行錯誤したのだが、最終的にクライアントとなるSiliverlightプロジェクトからは独立させたEntityプロジェクトへ参照設定ができないことが判った。(エラーになって追加できない。
Silverlight用のランタイムが.NETランタイムのサブセットになっているからだと類推する。
ちなみに、この「10行でずばり」のサンプルではクライアントをコンソールアプリケーションとして実装しているので問題にはならない。

しかたが無いので、最後の砦の本家MSDNを調べる。
Silverlightの自己追跡エンティティというのがあったので飛んでみる。


これを見ると、Entityプロジェクトなどは通常のクラスライブラリプロジェクトではなく「Silverlightクラズプロジェクト」として作る必要が有りそう。(直接的な原因かどうかは判らないが)

この記事を参考に@ITの「提供サンプルを」修正してみる。
試行錯誤し、エラーを消しながら書いているので順番は適当である。

  1. ソリューションに「Silverlightクラスライブラリ」プロジェクトを追加。(Entityプロジェクト)
    image
  2. AddressBookDataプロジェクトのAddressBook.edmxをAddressBookSilverlightApp.Webプロジェクトにコピー(既存項目の追加で行う)。
    現状では、このプロジェクトからAddressBookDataプロジェクトを参照しているのだが、Entityを別Silverlightクラスライブラリプロジェクトに切り出すので、プロジェクトの種類の違いからEntityプロジェクトを参照できないため。
  3. 追加したedmxから元記事の手順で「ADO.NET self-Tracking Entity ジェネレータ(Model1.tt)を追加
    image
  4. Entityプロジェクトに、今作成したModel1.ttをリンク追加。
    Entityプロジェクトを右クリックして「既存項目の追加」
    image
  5. AddressBookSliverlightApp.Web修正
    ここで、AddressBookService.svc.csになぜからエラーが出るので修正。(項番9の載せ替えを行った後のほうが良いかも)
    image
    なんだかよくわからないが、このメソッドは今回のサンプルでは使っていないため削除。(このメソッドに付いているOperationContract属性も削除する)
    image
    型指定が必要だと怒られているようなので型指定を追加。
    container.Entries.ApplyChanges<Entry>(entry);
  6. AddressBookSilverlightAppプロジェクトから以下を削除してEntityプロジェクトを参照設定追加
    AddressBookModelSelfTracking.cs
    Category.cs
    Entry.cs
  7. Entityプロジェクトに「System.Runtime.Serialization」への参照設定を追加して、プロジェクトのプロパティから「規定の名前空間」をAddressBookSilverlightApp.Webに変更。(これを合わせておかないとサービス参照の追加でEntityが自動生成されるのを抑止できないようだ)
  8. AddressBookDataプロジェクトは要らなくなったので削除
    (AddressBookService.svc.cs、MainPage.Xaml.csでusingしているので削除)
  9. AddressBookSilverlightApp.WebプロジェクトのAddressBookService.svcを削除し「Silverlight対応WCFサービス」を同じ名前で追加してメソッドを全て載せ替える。
    (同じ名前で追加するとWeb.configの記述が重複するようなので追加する前に削除)
    image
  10. AddressBookSilverlightAppプロジェクトのサービス参照「AddressBookServiceReference」を削除して再度追加してみる。
    (サービス参照の追加でエラーになるときは一旦ビルドすると良いようだ)
  11. AddressBookSilverlightAppプロジェクトの「MainPage.Xaml.cs」にAddressBookSilverlightApp.Webのusingを追加する。

0 件のコメント:

コメントを投稿

私が最近チェックした記事