.NETのO/RマッパーSomaを作り変え中
C#で作っていたのですが、F#が面白いのでF#で作り直すことにしました。Somaは、SQLやSQLに埋め込まれた簡易的な式言語をパースしたりするんですが、C#では正規表現をつかって何とかしてました。F#ではこのあたりの処理にF# PowerPackのfsyaccとfslexを使えるんですよね。これが乗り換えた大きな理由だったりします。
で、簡易的な問い合わせは動くようになりました。こんな感じです。
type Department =
{ DepartmentId : int;
DepartmentName : string;
VersionNo : int;
ModifiedDate: DateTime }type MyDbConfig() =
interface DbConfig with
member this.Invariant
with get() = "System.Data.SqlClient"
member this.ConnectionStrings
with get() = ConfigurationManager.ConnectionStrings.["Soma.Core.IT"].ConnectionString[<Test>]
let ``connect to DB with Soma``() =
let config = MyDbConfig()
let departments =
Sql.query<Department> config
<@ let id = 2 in () @>
"select * from Department where DepartmentId = /* id */0"
departments |> List.iter (fun d -> printfn "id = %d, name = %s" d.DepartmentId d.DepartmentName)
上のコードを実行すると、次のような結果が出力されます。最初の行は実行したSQLの簡易的なログ。3行目が上のテストコードでprintfnしているもの。
sql log: select * from Department where DepartmentId = @p0 id = 2, name = Sales
ポイントは、
といったところです。
条件分岐を使ってSQLを動的に組み立てるには、SQL中に /*% if ... */ と /*% end */ で記述します。
[<Test>]
let ``connect to DB with Soma : using if expression comment``() =
let condtion id = id > 10
let config = MyDbConfig()
let departments =
Sql.query<Department> config
<@ let id = 2 in let condition = condtion id in () @>
"select * from Department where
/*% if condition */
DepartmentId = /* id */0
/*% end */"
departments |> List.iter (fun d -> printfn "id = %d, name = %s" d.DepartmentId d.DepartmentName)
上のコードを実行すると、こういう結果になります。conditionがfalseに評価されるのでwhere句以降は除去され全件取得になります(2件しかないけど)。
sql log: select * from Department id = 1, name = Account id = 2, name = Sales
conditionがtrueになるように変えてみると結果はこう変わります。要するにwhere句がちゃんと生成されます。
sql log: select * from Department where DepartmentId = @p0 id = 2, name = Sales
今後は、更新系のSQLの自動発行やページングのSQLへの変換処理などもろもろを作っていく予定。今年中に完成できればいいかなぁといった感じです。ちなみに、Entity Frameworkは使わないことにしました。
F#を使ってみて実感しましたが、まちがいなくコード量は短くなりますね。かなりいいです。特にテストが書きやすい。
もちろん、Visual Studioがリファクタリングをサポートしてくれればなどの物足りなさはありますが、そこは我慢。次のバージョンではサポートされるよね?
追記 2011/01/17
そういえばソースコードですが下のリポジトリの最近の日付の「Soma.Core」や「Soma.Core.UT」などがF#のプロジェクトです。「Soma」はふるいC#のコード。興味のある方はぜひご覧ください(そして意見あればぜひください)。
http://soma.codeplex.com/SourceControl/list/changesets