2009年4月15日水曜日

ADO.NET DataServices v1.5 CTPの行カウント機能を実験

 

ダウンロードしたけど試せていなかったv1.5CTP1のrow count機能を触ってみました。

 

以前のバージョンではそもそもCountが未実装だったので、たとえば「キー値を渡した存在チェック」みたいな一般的な処理を行う際にも回りくどいことをする必要がありました。

んで今回のこの機能追加ですが、2種類の方法で行数取得が可能となっています。 (詳しくはここ

 

  1. Count オプション(pseudo selector)
  2. InlineCount オプション(query option)

 

まず最初のCountですが、これは完全に結果セットの行数を単純にスカラー値として返すクエリ。

 

たとえば、以下のように返してくれます。

 

  • MyService.svc/Products/$count

20

  • MyService.svc/Products/$count/?$filter=CategoryId eq 3

6

 

対してInlineCountはというと、クエリ結果のフォーマット内に結果行数の情報を格納して返す形となります。

 

例としては、

  • MyService.svc/Products?$filter=CategoryId eq 2&$inlinecount=allpages

 

などと投げると、レスポンスの中に

<m2:count xmlns:m2="4</m2:count">4http://schemas.microsoft.com/ado/2008/11/dataservices/metadata">4</m2:count>

といった感じで m2:count タグが挿入されるのがわかります。

でも、クライアントからコードで取得するときは、

var query =
     from p in ctx.Products
     where p.CategoryId == categoryId
     select p;
int cnt = query.Count();


と単純に書いても動いたので、明示的にInlineCountの指定をしなくてもとりあえず大丈夫なのかもしれません。



(以前はquery.Count()の部分でNotSupportExceptionだったと思います)。



ただし、



var query =
     from p in ctx.Products
     where p.Id == id	//Id は主キー
     select p;
int cnt = query.Count();  // NotSupportedException!!


のように、主キーで問い合わせを行うパターンではCountでNotSupportedExceptionが出てました。




  • MyService.svc/Products(7)



のような問い合わせ形式には現状対応していないみたいんでしょうか。



 



とりあえずは以下のように逃げられますがね。まあこれはあくまでワークアラウンドということで。



DataServiceQuery<Product> query =
     (from p in ctx.Products
      where p.Id == id
      select p) as DataServiceQuery<Product>;
var ps = query.Execute();
int cnt = ps.Count();


と、ここまで書き連ねておいてなんですが、これによるとv1.5の DataServiceContext.IgnoreResourceNotFoundException プロパティを使えば、いちいちRowCountなんぞとらなくても、FirstOrDefaultで存在チェックできそうですね。。。



もっと早く気づけば良かったw 疲れたんでこの検証はまた後日。

2009年4月13日月曜日

.NET RIA Services Overviewを読んで

 

Microsoft .NET RIA Services Overview ~ Mix09 Preview

 

Mix09のタイミングで公開開始されたPDFを一通り読んでみたので、忘れないようにメモ。

 

  • N-Tierアーキテクチャでのレイヤ間モデル・ビジネスロジック共有のためのフレームワーク&ガイドラインといったところで、とくにSilverlightにフォーカスしたもの。
  • EntityFrameworkまたはLINQtoSQLをサポートし、サーバーサイドでのモデルとビジネスロジック実装をクライアント側からも共有できるように、Proxyの自動生成を行う。
  • サーバー側実装はDomainServiceクラス(EF/LTSの選択によって継承元が異なる)に行う。
  • DomainServiceを参照するクライアントプロジェクトではビルド時に自動的にProxyクラスが生成される。また、Entityだけではなく、BLもProxyに反映される。
  • クライアント側ではDomainContextクラスを使用する。DomainContextではEntityの状態管理、変更トラックなどを行う。
  • クライアント側でもサーバー側と同じNameSpace、クラス名でモデルへアクセスできる。またINotifyPropertyChangeも自動的に実装される。
  • サーバー側のCRUD処理については、DomainContextにも同様のメンバが用意される。ただし更新系についてはあくまでContext内の状態変更を行うだけなので、サブミットされるまでは実際に更新されない。
  • クエリ系メソッドはクライアント側ではご丁寧に名前が変更される(Get,Fetch,RetrieveなどからLoadに)。サーバー問い合わせが非同期で行われているんだよ!との注意喚起を促すため。
  • 全般に規約が重視されているので、ファイル名やメンバ名などに注文がつく(属性によって回避可)。開発者の労力削減とチーム開発での可読性を向上する狙い。
  • カスタムのビジネスロジックも共有可能。その場合CustomやServiceOperationなどの属性を付加する。
  • EntityのバリデーションはSystem.ComponentModel.DataAnnotationsに含まれる属性でマーク可能。もしお手製が必要なら共有クラスにValidatorを追加する。

 

なんて感じでかなりパワフルなプロキシを作ってくれるという代物です。

自動生成のプロキシに依存する部分が大きいだけに、ここがスキ・キライが分かれるところかもしれません。

でもBLの共有も含めてひとくくりにレイヤの壁を取っ払いたいときには、現実的で手っ取り早いアーキテクチャではないでしょうか。

規約ベースなところも好感で、小規模・短納期のプロジェクトでは主流になっておかしくないと思います。

 

また、最後のほうに Silverlight用の DomainDataSource の説明があって、RIA ServicesおよびDataGridと連携して、

  • データの自動ロード
  • コントロールへのパラメーター割り当て
  • ソート
  • グループ化
  • フィルタリング
  • ページング
  • エディット

 

などがXAMLで記述できるとのこと。

Validatorによる検証も含めて、DomainドリブンなUIがSilverlight上でもサクッと実現できるのは非常にいい感じです。

あとはADO.NET DataServicesとの棲み分けが気になるところですね。

まだ日本語環境対応版の気配がないんで、仮想環境に英語版VSをインストールして試してみようかと思います。