sandbox

Scala, Android, Architecture, Management, Service Design あたりを主戦場としております

LINQ to Entities で _ , % を使ったワイルドカード検索

たまにはブログ書こう。。という事で。

背景

SQL で使える _(アンダースコア), %(パーセント) のワイルドカードがあります。
このワイルドカードを使ったパラメトリックなクエリを LINQ to Entities (以下 L2E) で純粋に実現しようと思うと、StartsWith, EndsWith, Contains と Expression Tree & Lambda Expression を使って面倒な実装をする必要があります。
まだワイルドカードはひとつまでとかだったらいいですが、複数となるといちいちパースして、Expression Tree 組み立てて、というのは暇な時しかやる気がおきません。


そこでなんとか簡単に実現する方法がないかと調べていたのですが、ある方法ですぐ実現できました。

結論

Object Query を使う です。
以下、例。

// 実は ObjectQuery.Where が使えるので、IQueryable.Where でなく ObjectQuery.Where で。
ObjectQuery<Products> query = e.Products.Where("It.ProductNumber like 'AA%%-00%%'");

// ObjectQuery は IQueryable を実装しているのでそのままキャスト。
IQueryable<Products> products = (IQueryable<Products>) query;

※最初から ObjectQuery でいいじゃん、と言われるかもしれませんが、ADO.NET Data Services を使っているので L2E 上で実現する必要がありました。

なんで使えるの?

何かソースがあって使えると判断した理由ではないので、明確に何故には答えられません。。
気づいたのはデバッグをしている時で、L2E のクエリにブレイクポイントを設定して、クエリ処理中のデータ型を見てみると IQueryable ではなくて ObjectQuery となっていました。
であれば、ObjectQuery.Where が使えるんじゃないかと思って使ってみたら使えた、という流れです。

詳細は Entity Framework のアーキテクチャを追わないとはっきり分からないかもしれませんが、おそらく L2E のクエリが ObjectService によって処理される際に、内部的に ObjectQuery が使われてるんだろうと思ってます。

まとめ

L2E のタイプセーフさはなくなりますが、ADO.NET Data Services の Service Operation の様に IQueryable を返す必要があって、パラメトリックなクエリに対応したい場合に役立つと思います。


なんかドキュメント見落しているだけなのかもしれませんが、ふつう気づかないよなぁ、と思ったので公開メモでした。