実は自分は LINQ 大好きである。
LINQ の使えない C# なんてもう考えられない。
もともと Prolog や Haskell の体験もあり、また、SQL は好んでふんだんに使うし、jQuery のセレクタ万歳なので、宣言指向、How より What、集合操作は大好きである。
当然のごとく、LINQ to SQL や LINQ to Entity も多用する。
しかし、である。
小粒でアドホックなデータベースへの SELECT クエリを、ささっと書きたいときもある。
昔ながらに DataAdaptor などを使いながら DataSet や DataTable で結果を入手してもよいのだが、シンプルなオブジェクトにマップできたほうが、インテリセンス中毒である自分にとっては大変楽である。
となれば LINQ to SQL の出番なのだが、しかし、たかだかそれだけのために .dtml をプロジェクトに新規追加して、デザイナを開いて、サーバーエクスプローラからテーブルをドラッグ&ドロップして...というのは、なんだか馬鹿げているというか、大仰に過ぎると思う場面もある。
LINQ to DataSet という選択肢もある。
しかし、Fields<型>("カラム名") 拡張メソッドなどが用意されているものの、だからといって、特段、コードが堅牢になる・書きやすくなる・読みやすくなることはない感じがする。
もちろん、AsEnumerable() してからクエリ構文でいじったりなど、LINQ to DataSet を重宝しているケースも少なくないが、今回のテーマとはまた別の話。
で。
実は、LINQ to SQL を構成するクラス群のひとつであり、.dtml デザイナが吐くコンテキストクラスの基底クラス、System.Data.Linq.DataContext クラスをそのまま使えば、SELECT クエリに関しては簡単な O/R マッピングができてしまうのだ。
コード見たほうが理解は早い。
public class PersonType {
public int PersonID { get; set; }
public string PersonName { get; set; }
}
var connnection = new SqlConnection(...);
var context = new DataContext(connection);
var persons = context.ExecuteQuery<PersonType>(
@"SELECT PersonID, PersonName
FROM Persons
WHERE PersonID BETWEEN @p0 AND @p1",12, 34);
こんな感じで、Persons テーブルから PersonID が 12~34 であるレコードを取り出してきて PersonType 型のオブジェクトにマッピングし、IEnumerable<PersonType> で入手、ということができる。
SQL 文の SELECT 中の選択リストを、マッピング先クラスの同名のプロパティにマップしているわけだ。
ごくごく些細で局所的な SELECT クエリを行いたいときは、本当にこれは便利。