.NETで作る!

.NETに関するあれこれ(C#、VB.NET)

フルORMの神髄はダーティチェックだ!

ORMの構成要素はなにか?

ORMの構成要素は、ざっくりいって

  • Object Relation 変換(Load)
  • Realation Object 変換(Save)

の2つです。

このうち「Load」は、列値をプロパティにはめていくだけなので比較的楽です。*1

面倒なのは「Save」。 プロパティを列にはめるだけだから似たようなもんじゃないかと思いますが、

  • 追加なのか更新なのか、削除なのかわからない

という問題があります。*2

というわけでして、フルORMするならこの問題を解決する必要があります。

つまり、Load、Saveとは別に

  • 何が更新されたかを調べる機能

が必要になってきます。

ダーティチェックするには?

何が更新されたかを調べるには

  • データベースから呼び出した値をメモリにとっておき(アーカイブ)
  • データベースに書き戻す前に比較して変更点を取得する(ダーティチェック)

というステップを踏む必要があります。 このうち、アーカイブは楽なもんで、

dic.Add(prop.PropertyName, prop.GetValue(instance, Nothing)

のようなプロパティ辞書を作るだけでいいです。

問題はダーティチェック。というより、検査対象のインスタンスとアーカイブの紐付の仕方。 わかりづらいので、コードで説明するとアーカイブの管理はこんな感じになるはず。

Dim archives As Dictionary(Of Object, Archive)
archives.Add(key, archive)

問題なのは「key」を何にするか…ということ。 インスタンスそのものをキーにすると考えたいところですが、それはあくまでObjectの捉え方なので、Relation(Database)に戻すことを考えるとイマイチ。 というわけで、Relationの考え方から

  • テーブル名
  • 主キー列名とその値

をkeyとするのが妥当でしょう。

これを具体的に掘り下げてみると

  • テーブル名≒クラス名なので、特に問題なく解決。
  • 列名≒プロパティ名なのですが、どのプロパティが主キーなのかはわからない。
  • 値はプロパティが特定できれば取得可能。

こんな感じになります。

主キーがわからないとどうにもならないので、何らかの方法で主キーを特定する必要が出てきます。

解決方法としては

  • プロパティにカスタム属性をつけて特定する
  • プロパティ命名規約を決めて特定する

のどちらか、または両方でしょうね。

この問題が解決するとダーティチェックが可能になるわけですが、主キープロパティの特定ができると、Saveはもちろん、Loadもその情報をもとに行えばよくなるため、理論上ORMが作れることになります。*3

*1:単一Objectマッピング限定の話。それ以上に踏み込むとかなり大変になる。正直Saveよりややこしいんですけど話を簡単にするために楽ってことにします。

*2:面倒だから全部MERGE文でやるという方法もなくはないでしょうが、その方法では削除ができません。

*3:あとはクラス名とテーブル名のマッピングとかその辺ぐらい。ここは本当に辞書レベルの話のためこれといった課題はありません。

. .