Quantcast
Channel: いげ太の日記
Viewing all articles
Browse latest Browse all 26

Micro ORM を128行で

$
0
0

今年も F# Advent Calendar 2013の季節がやってまいりました。というわけで、初日、12/1担当の私です。

タイトルの通りなわけですが。ここで訂正です。「128行で」と申し上げましたが、よく数えたら124行でした。加えて、「Micro ORM」と書きましたが、Micro RRM でした。Micro Record-Relational Mapper です。はいそこ、レコードも結局オブジェクトでしょ? とか言わない。

ソースは github に上げておきましたので、そちらでご覧ください。

https://github.com/igeta/FsugJp.MicroRrm

実装コードはすべて FsugJp.MicroRrm.fsに書いていて、繰り返すようですがたった124行です。で、簡単な使い方を Sample.fsxで示しています。

何ができるか? 何ができないか?

現状、DB からのデータの読み込みのみできます。つまり、SELECT 文を投げて、その結果セットのデータを指定したレコードに詰めて返してくれる、ということだけをします。結果セットとレコードは、対応するように、フィールド名およびその型を合わせておく必要があります。追加・更新・削除はできません。

使い方は?

Sample.fsx の通りですが、ざっと解説。

まず、必要な結果セットに対応するレコードを作ります。いわゆる POCO ですね。POCR と言ってもいいかもしれない、ダメかもしれない。まあ何でもいいです。ありがちには、テーブルに対応するような型として作ります。説明上、たとえば MyTable とでもしましょうか。

んで、それに DB からデータを取得して詰め込むわけですが、そのための API として関数が2個あるだけでして、readBy と read です。名前でお気づきかもですが、実質1個って言ってもいいようなものですね。

readBy から説明します。DbRecord.readBy<MyTable> dbConnection "SELECT * FROM MyTable"のような形で使います。第1引数で指定したコネクションに対して、第2引数で指定した SQL 文字列を実行し、その結果セットを seq<MyTable> として返します。

read は、readBy の SQL 文指定を省略した版です。C# ならオーバー ロードで実装するところですね。DbRecord.read<MyTable> dbConnection のような形で使い、MyTable テーブルのすべてのレコードを取得します。内部的に readBy を呼んでいて、それに渡す "SELECT * FROM MyTable"な SQL を勝手に作ってくれるってだけのものです。

何がうれしいか? 見どころは?

F# 的にうれしいのは、すでに説明した通り、オブジェクトでなくレコードでデータが取得できるというところです。パターン マッチが使えます、比較演算も構造的に行われます、と。それから、Null 許容なフィールドのデータは、Nullable<'T>でなく 'a option の値としてマップするようになってます。やっぱ option でしょ、そうでしょ? すべては構造的な値として、ね。

SQL Server 的にうれしいのは、レコードを DbSchemaAttribute 属性が付与されたモジュール下に定義することによって、そのモジュール名をスキーマ名として使用する、というところ。具体的には、[&ltDbSchema>] module MySchema に MyTable レコードを定義することにより、read によって自動生成される SQL が、"SELECT * FROM MySchema.MyTable"となります。そうでない場合は "SELECT * FROM MyTable"です。まあ、やや蛇足的な機能ではあります。

それと、当たり前に欲しい機能として、レコードのフィールドと結果セットのフィールド、これらが異なる定義である場合でも、きちんと動きます。わかりにくいので具体例で言うと、MyTable レコードにはフィールド F1、F2、F3 を定義しました、でも DB 側の MyTable テーブルにはフィールド F1、F3、F5 がありますよ、という場合でも、ちゃんと F1 と F3 の値だけを取ってきてくれて、F2 にはそのフィールドの型の規定値をセットします。

今後の展開は?

もしご好評いただくようなら、開発を継続、機能拡張していきたいです。ホントに好評なら NuGet に登録したりとか? わかりませんが。

目下、個人的にちょっとやりたいなーと思っているのは、「DB 側のテーブル名やフィールド名はスネーク ケースで作ってるんだけど、F# でマップするときはキャメル ケースにしたいんだよねー」な要求への対応。あと、DB 側の名前に F# のキーワードが使われていた場合への対応とか。

それから追加・更新・削除をどうするか。そもそも ORM にも Micro ORM に詳しくないのでどうすればいいやらという感じですが。

まとめ

F# 的な Micro ORM とは、という議題についての取っ掛かりのようなものになればということで、ごく簡単なコードを示したので作ってみた、というところです。実用性は不明です。

ただ、DB からサクッとデータが取ってこれて、それを fsi でごにょれるの、割と便利。


つーわけで、F# Advent Calendar 2013、初日終了っす。2日目は 7shi さんです。バトンターッチ!


Viewing all articles
Browse latest Browse all 26

Trending Articles