↓これがObjectContextにアタッチされていないエンティティを使って、DB更新してみるコード。Framework)AttachToでObjectContextに空のエンティティをアタッチしておいて、ModelBinderで復元したエンティティの値をApplyPropertyChangesで反映させる流れです。ObjectStateManagerを使うともっと綺麗にできるのかも?↑このコードはRepositoryクラスに。コレを呼び出すControllerコードは↓。はしょってるんですが、何となく雰囲気は伝わるかな~、と思います。Frameworkを使ってProducts/Categoriesだけのエンティティクラスを作成してます。HomeControllerのIndexが一覧ページになるようにしておいて、Editを追加しただけのプロジェクトで試してます。今回はコレに加えてUnityを使ってDIでObjectContextをRepositoryにコンストラクタインジェクションと、RepositoryをControllerにコンストラクタインジェクションさせるようにしてみました。Unityを使ったControllerFactoryなんかはMvcContribにもコードがあったりするので、そちらを参考にするのが近道です。MvcContribのUnityControllerFactoryはLifetimeManagerを指定しないので、Resolveの度に新しいインスタンスを作ります(TransientLifetimeManager)。HttpContextにObjectContextを入れておいて、同じコンテキストなら無駄使いしないようにするためのHttpContextLifetimeManagerクラスを用意。Blog」に書かれてる、HttpContextLifetimeManagerを使わせてもらいました。Get/Set/RemoveのoverrideでHttpContextを使うようにしてるだけですね。ObjectContextのインスタンスがどうなってるのかを確認するコードをHomeControllerに書いて確認。}Debug内ではObjectContext.GetHashCode()を出力するようにしてます。コンストラクターで渡されるRepositoryはUnityに任せたもので、OnActionExecutingとOnActionExecutedではコンストラクタで渡されたものを出力し、Index内でそれぞれ(Other-1/2)新しくリポジトリのインスタンスを作成(Resolve)して出力させてます。TransientLifetimeManagerを使った出力。Constructor:6658142OnActionExecuting:6658142Other-1:5603269Other-2:50559794OnActionExecuted:6658142Otherはそれぞれ違うインスタンスが生成されてますね。HttpContextLifetimeManagerを使った出力。Other-1/2は全然違うのが出力されますね。Constructor:60183783OnActionExecuting:60183783Other-1:60183783Other-2:60183783OnActionExecuted:60183783Otherも同じインスタンスです。Global.asaxに以下のコードを追加してUnityに登録してます。ContainerControlledLifetimeManagerを使うとSingleton。blog」に書かれてるようなジェネリックなリポジトリを書いてみようかな~と試してみたんですが、どうですかね。簡単な機能実装ならいいかもしれないけど、この辺は機能ドメイン毎にちゃんと書いた方がいい気がする。ところで、EntitySet名ってエンティティクラスから簡単に取得する方法ってないんですかね。EntityKeyには入ってるみたいだけど、アタッチして無いとnullで取り出せないじゃないですか。今回はずるっこして、エンティティクラス名+"s"として生成してます。今回もプロジェクト添付しておくので、動かしてみたい方はどーぞー。あ、データベースファイルは添付してないです。Unity2009年5月23日土曜日イケメンはしゃべりも上手い久しぶりにアメージングで試合。最近になってゴーリーが誰一人これなくなり、代わりにオグさんがやるらしく、プレーヤーが足りなくなる。ほら、ビシッと決めれるプレーヤーがいないと、あれじゃないっすか。今期になって色々あって全然試合にも出れず、チームにも迷惑をかけてたな。なんてことは、これっぽっちも思ってないんだけどさ。普通に勝ち越してるし。いてもいなくても勝敗に関係ないじゃん...。前期のギリギリプレーオフに比べれば、勝ち越してる今期のほうが全然気が楽だから、小さい事は気にしない。9:30開始だから心が折れそうだったけど、試合が久しぶりだったからかワクワクしすぎて目覚ましより早く起きれた。今日はいい感じでプレーできる気がする。そんな気がするときはたいていいい感じでプレーできないんだけどね!レフェリーがタカチさんでなんか不安だったけど試合開始。一点目を決めたんだけど、タカチさんなかなか笛を吹かず、こっち見てる。あれ?入ってるよ?なんで認めないんだ!早く笛を吹いてオレの得点だとコールしたまえよ!イヤそうな顔しながらしょうがなくコールするレフェリー...。久しぶりなんだからもう少し優しくして...。2点目をセト君のが決めたんだけど、ここで事件発生。セト君は開始時間に間に合って無くて、背番号空白でロースターだしてたのをすっかり忘れてた。ベンチマイナーで無駄にキルプレーっす。それは自分の責任なのでしっかりキープして時間を使い守りきれました。なんやかんやと前半結構点を取られまして。そもそもシュートを打たせたらダメなのに、守り方間違えてた。前半終わったところで2-4。後半しっかり攻めて点を取ればいいから、これ以上失点さえしなければ逆転できる。気楽に考えてたけど、アメージングが久しぶりなのをすっかり忘れてたよ。滑っても滑っても全然スピードにのらない。ウィールがぼろいのもあるけど、滑りかたが戸塚の堅いリンク用の滑りかたになってたみたい。相手を振り切れない滑りになってて、無駄に疲れた。そんな不安をシンゴが吹き飛ばしてくれた。前回の試合もそうだったらしいんだけど、あれよあれよと追いつき逆転。君はそんなしっかり者のプレースタイルじゃなかったじゃないか。ここぞというときに外すのがシンゴスタイルじゃなかったのか?どうやら、たけはら不在の間に、チームを引っ張ってたのはシンゴだったみたいね。おぬし、なかなかのもんだな。それに引き替えたけはらさんは、足で蹴り入れたんじゃないかという疑惑のゴールがあったり。相手のペナルティーによるパワープレーで疑惑を晴らすかのようなディフェンスラインからのスラップで名誉挽回(汚名返上?)。最終的に相手チームのスタミナ切れで何とか逃げ切って勝てたけど、内容的には反省点の多い試合でした。次回以降もう少し丁寧に大人のホッケーをしないとね。そうそう、マリちゃんとは初めて一緒に試合出たけど、今日の試合ではマリちゃん含め、なんと全員ポイント!ミカさんもイマイちゃんも、意外なことにミチも!全員にポイントが付く試合はあんまりないけど、それが出来た時は一番嬉しい。最後にちょっとイマイちゃんがケガしちゃって、最後までプレー出来なかったが残念でした。話は変わるんだけど5/20にボーランドソリューションセミナーっていうのがあってそれに行ってみた。個人参加は一人だけで、少し場違いな気がしなくもなく...。テストツールに興味があったからというより、ケースケがしゃべるってことなんで行ってみた。ファンにはたまらない。無料イベント最高!いやいや、そうじゃなくて、ケースケがしゃべる内容がRIAってことだったんで行ったわけです。RIAの話もリサーチした数値の説明があって現状どういうとらえ方をしてるのかを分かりやすく説明してくれたり、今後もっといろんなデバイスにRIAを展開していく話とか、デザイナーとデベロッパー間での効率を良くするためのCatalystのデモをやったりと盛りだくさんで面白かったよ。面白かったのは市ヶ谷の駅前で迷子になって地図とにらめっこしてるたけはらさんをケースケが見つけて会場までつれてってくれたところだね!ちなみに駅前迷子の前に、電車の乗り換え間違えて全然違う方向に向かってて途中慌てて乗り換えてなんとかたどり着いたという事件があったりなかったり。最近3回東急東横線に乗ったんだけど、そのうち2回電車が遅れるということもあったりなかったり。ホッケー2009年5月13日水曜日HandleErrorの使い方そういえば、今月に入って全然エントリを書いてなかった事に気がついた。人に言われて気がついた。本を読んでて、頭がプシューってなっててさ~。MVCでHandleErrorを使って、HTTPステータスコードに合わせたエラーページを用意する方法が日本語情報として無いかもとふと思ったので書いておきます。使い方はアクションにHandleError属性を指定して、web.configのcustomErrorsのモードをOn/RemoteOnlyに設定しておけば、defaultRedirectが表示されるというものです。}コントローラに指定しても、アクションに指定してもいいですよね。それぞれに指定した場合、コントローラの普通はHandleErrorが優先されます。上記コントローラに以下のアクションを追加してみると確認できますね。}ViewにThrowExceptionへのリンクを作成して表示させてみたのが↓こちら。普通に標準のエラーページが表示されます。アクションのHandleErrorにはViewを指定しているにもかかわらず。これをアクションに指定してるほうを優先させるにはコントローラに指定してるHandleErrorの優先順位を下げればOKです。Orderは0スタートなので1以上なら何でもいいです。すると今度はどういう表示になるか確認。グレート!ちなみにリリース版のVSテンプレートが出力する~/Views/Shared/Error.aspxでは例外情報の表示コードが無くなってるので分かりにくいですが、このページは少し特殊でInheritsが単なるViewPageじゃなく、例外情報が渡されるように型付きViewPageになってます。%>なので、Viewページ内でModelを参照するとアクション内で発生したExceptionが参照出来るようになってます。自分でエラーページを定義する場合のInheritsを上記のように変更しておけば、自動で参照できるという寸法です。ちなみに上記スクリーンショットのViewは~/Views/Shared/Exception.aspxというのを作成して表示してます。例外を捕捉して専用エラーページを表示するのももちろん必要だと思うんだけど、そこはやっぱりHTTPステータスコードに合わせたエラーページを定義して、レスポンスのステータスコードも合わせた方がサーチエンジンにもエラーが認識できるし、RESTfulな感じがして素敵だと思いませんか。上記のページの場合レスポンスされるステータスコードはなんになってるか確認してみる。例外だからそれで良し。idを指定してDB検索して一致するデータがない、なんて時は404で返したいな~、なんて思いませんか。試しに、web.configのcustomErrorsを以下のように変更。</customErrors>で、HomeControllerに以下のコードを追加。}ErrorsControllerを追加して、HTTPステータスコードに合わせてViewを返すようにします。}で、Home/BadRequestにアクセスしたのが↑。拡大すると見えるけど、200が返ってます。400が返って欲しい。そんなときはViewResultを書き換えてしまいましょう。}こんな感じのクラスを作成しておいて、Errorsコントローラでこっちを利用するように変更。}で、同じアクションを実行したのが↓こちら。