はじめに

Load(Relation Object Mapping) するには?にて、ModelLoader.From(Of T)メソッドがある程度理解された方向けのドキュメントです。
まだ読まれていない方は先に読んでおいてください。

事前準備

1. 参照設定を追加

利用するには以下のプロジェクトを参照設定に加えてください。
Project file 必須 備考
Kairyu.vbproj 必須 フレームワークの基礎処理が記述されています。
Kairyu.Load.vbproj 必須 RelationObjectMapping処理が記述されています。
Kairyu.Save.vbproj 必須 ObjectRelationMapping処理が記述されています。
Kairyu.Extensions.Connection.vbproj 必須 DB接続の基底となる処理が記述されています。
Kairyu.Extensions.Connection.Oracle.vbproj 任意 Oracle接続の実ロジックが記述されています。
Kairyu.Extensions.Connection.SqlCe4.vbproj 任意 SqlServerCe4接続の実ロジックが記述されています。
Kairyu.Extensions.Connection.SqlCe35.vbproj 任意 SqlServerCe3.5接続の実ロジックが記述されています。
Kairyu.Extensions.IO.vbproj 必須 DB接続ロジックが記述されています。
  • 「任意」と書かれたファイルは使用するDBMSに合わせて必要なものだけを利用してください。
  • ここではプロジェクトファイルを参照していますが、「DLL」を参照しても構いません。
  • 今回初めて「Kairyu.Save.vbproj 」というプロジェクトを参照します。

2. Modelクラス、テーブルを用意する。

こちらは「Code First(CREATE TABLE)するには?」を参照して、クラスとテーブルを作成します。
なお、こちらのページで作成されるクラスとテーブルは以下の通りです。

Prefecture.vb
Public Class Prefecture
    Public Property PrefectureID As Integer
    Public Property PrefectureName As String
End Class
テーブル:Prefectures
PK Column Name Type NULL
Y PrefectureID int N
PrefectureName nvarchar(100) N

使い方

まずサンプルコードを示す前に、保存メソッドの仕様について説明します。
Public Class ModelSaver
    Inherits ModelLoader
    ・・・
    Public Sub Save(model As Object, strage As Strage)
    ・・・
End Class

第1引数のmodelはDB保存したいインスタンスを指定します。
第2引数のstrageとは、ダーティチェックをするKairyu.Save.Strageクラスのこと指します。
初めて出てきたクラスですので、概要を以下に記述します。

Kairyu.Save.Strageクラスは・・・
  • Public Sub Regist(instance As Object)メソッドで指定されたインスタンスを内容を記憶する。
  • Public Function IsDirty(instance As Object) As Booleanメソッドで指定されたインスタンスがダーティであるかどうかを返す。
  • RegistしていないインスタンスをIsDirtyメソッドにかけると、True(INSERT)になります。
  • Registしており、かつ変更をしていないインスタンスをIsDirtyメソッドにかけると、Falseになります。
  • Registしており、かつ変更しているインスタンスをIsDirtyメソッドにかけると、True(UPDATE)になります。
  • 下層カスケード機能もありますが、そちらはSave応用編にて説明します。

ややこしいので、ここはさらっと流してください。
次は新規保存する例を挙げます。

VB.NET
0:  Imports Kairyu.Extensions.IO
0:  Imports Kairyu.Load
0:  Imports Kairyu.Save
・・・
1:  Dim m As New Prefecture With {.PrefectureID = 1, .PrefectureName = "北海道"}
2:  Dim s As New Strage
3:  DB.Transact(
4:      Sub(r As ModelSaver) 
5:          r.Save(m, s))
6:      End Sub)
  • ORMのコードを記述するときは、拡張メソッドを使用するために「Kairyu.Load」をインポートしておいてください。

1行目はモデルの宣言です。特にフレームワークとは関係のない、普通のコードです。
2行目は先程説明したStrageクラスの初期化です。なぜインスタンスしないといけないのかは後程説明します。
3行目以降はフレームワークのコードです。これは以下のように処理されます。
  • 2行目:DB.Transactメソッドにて、DBへ接続し、トランザクションを開始。その後デリゲートを実行。
  • 5行目:ModelSaver.Saveメソッドにて、PrefectureクラスのINSERT文を作成。もう少し補足することがありますが、それは後程説明します。
  • 6行目:DB.Transactメソッドが終了します。この時、トランザクションをコミットして、DB接続を終了します。

まだややこしいので、ここもさらっと流してください。
続いて更新保存する例を挙げます。

VB.NET
0:  Imports Kairyu.Extensions.IO
0:  Imports Kairyu.Load
0:  Imports Kairyu.Save
・・・
1:  Dim m As Prefecture = Nothing
2:  Dim s As New Strage
3:  DB.Transact(
4:      Sub(r As ModelSaver) 
5:          m= r.From(Of Prefecture ).WhereKeyEquals (1).ToItem
6:          s.Regist(m)
7:          m.Prefecture = "青森県"
8:          r.Save(m, s))
9:      End Sub)
  • ModelSaverはModelLoaderを継承していますので、Load処理もできます。

5行目のLoad処理は以前に説明した内容ですので、省略。
6行目に注目。新規登録サンプルでは使用しなかったRegistメソッドを使用しています。
これは
  • DBから読み込んだ直後(≒DB値)の情報を記憶しておく。
  • DB保存時、DB値と比較をして、変更分だけ書き戻す
という処理を行うために記憶しています。
新規サンプルでRegistメソッドを使用しない理由は、DB値ではないからです。
7行目でモデルを編集し、
8行目で「現在値」と「DB値」を比較、変更分をSQLに変換してDBに書き込む。
という流れになります。

更新保存の例が一番わかりやすいと思いますので、これを踏まえたうえで、
ここで新規保存の処理を読み返してみてください。
なぜあのようなコードになるのか理解いただけるのではないかと思います。

ややこしくないか?

一般的なORMはStrageクラスに相当する処理はあまり表に出さないので、Strageクラスに登録するコードが煩雑に見えるかもしれません。
特にサンプルコードのような短いロジックにまとめて書くと顕著に見えるかもしれません。

ですが、実際のコードでは、
  • 新規作成処理と既存データ読み込み処理は入り口が別
  • 出口である保存処理は共通
となることが多いので、
  • 新規作成処理の時はRegistメソッドをコールしない。
  • 既存データ読み込み処理の時はDBから読み込んだ後、Registメソッドをコールする。
  • 保存処理は同じコード
となり、それほどややこしいコードにはなりません。

なぜStrageクラスを隠蔽せず表に出したのか?

以下の理由によります。
  • 読み込みだけして、保存しない場合、現在値をアーカイブする作業はオーバーヘッド。なので任意にしたかった。
  • Model自身がDB値を管理するという考えもありますが、その場合、ModelがORMに依存するとと考え、避けたかった。(Attributeは実害がないので、それは良いと判断)

Last edited Mar 12, 2013 at 3:38 PM by mk3008, version 5

Comments

No comments yet.