Linqを使えばデータアクセス層は簡単だ。
Linq to SQLを利用した簡単なデータアクセスコンポーネントを考えてみました。とりあえず検索系だけ。
Linqを使うと便利になる点が沢山あるのですが、気に入ったのが検索条件の部分をExpressionで記述できる点です。
たとえばこんな感じです。
a => a.state == "CA"
さらにAND条件をC#ライクに書いたり文字列長の比較までできる
a => a.state == "CA" && a.au_fname.Length > 2
これでQueryObjectを自作しなくてもOKです。しかも、Expressionなのでコンパイル時のチェックやもインテリセンスもききます素晴らしい!!
var biz = new AuthersManager(); var ret = biz.List( a => a.state == "CA" && a.au_fname.Length > 2, 3, 5); ret = biz.List(a => a.titleauthors.Count > 1, 0, 10); ret.ForEach(x => Console.WriteLine(x.Name)); public class AuthersManager : IDisposable { private AuthorsDomainDataContext _db; public AuthersManager() { _db = new AuthorsDomainDataContext(); } public ListList(Expression > q, int start, int count) { return _db.authors.Where(q).Skip(start).Take(count).ToList(); } ...
ちなみに、上記の例で検索処理で実行されるSQL文は以下のようになりました。
1番目
SELECT TOP 5 [t1].[au_id], [t1].[au_lname], [t1].[au_fname], [t1].[phone], [t1].[address], [t1].[city], [t1].[state], [t1].[zip], [t1].[contract] FROM ( SELECT ROW_NUMBER() OVER (ORDER BY [t0].[au_id], [t0].[au_lname], [t0].[au_fname], [t0].[phone], [t0].[address], [t0].[city], [t0].[state], [t0].[zip], [t0].[contract]) AS [ROW_NUMBER], [t0].[au_id], [t0].[au_lname], [t0].[au_fname], [t0].[phone], [t0].[address], [t0].[city], [t0].[state], [t0].[zip], [t0].[contract] FROM [dbo].[authors] AS [t0] WHERE ([t0].[state] = @p0) AND ((CONVERT(Int,LEN([t0].[au_fname]))) > @p1) ) AS [t1] WHERE [t1].[ROW_NUMBER] > @p2 -- @p0: Input NVarChar (Size = 2; Prec = 0; Scale = 0) NOT NULL [CA] -- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) NOT NULL [2] -- @p2: Input Int (Size = 0; Prec = 0; Scale = 0) NOT NULL [3]
2番目
SELECT TOP 10 [t0].[au_id], [t0].[au_lname], [t0].[au_fname], [t0].[phone], [t0].[address], [t0]. [city], [t0].[state], [t0].[zip], [t0].[contract] FROM [dbo].[authors] AS [t0] WHERE *1 > @p0 -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) NOT NULL [1]
*1: SELECT COUNT(*) FROM [dbo].[titleauthor] AS [t1] WHERE [t1].[au_id] = [t0].[au_id]