ダウンロードしたけど試せていなかったv1.5CTP1のrow count機能を触ってみました。
以前のバージョンではそもそもCountが未実装だったので、たとえば「キー値を渡した存在チェック」みたいな一般的な処理を行う際にも回りくどいことをする必要がありました。
んで今回のこの機能追加ですが、2種類の方法で行数取得が可能となっています。 (詳しくはここ)
- Count オプション(pseudo selector)
- 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 疲れたんでこの検証はまた後日。