簡易ORMフレームワークを作成してみる(8)

CRUD SQL文の生成

型指定されたDataSetにはテーブルに関する情報が豊富に保持されています。テーブル名、カラム名、プライマリキーなどなど。これらの情報を利用すると簡単に決まりきった検索・更新などのSQL文を作成することができます。

たとえば、SELECT文の生成であれば以下のようになります。QuryObjectBuilderと組み合わせると検索条件も含めて生成することも非常に簡単です。

public virtual DbCommand GetSelectCommand(DataTable schema, QueryObject query)
{
    QueryObjectBuilder b = CreateQueryObjectBuilder(query == null ? new QueryObject() : query);
    DbCommand cmd =  Adapter.CreateCommand();
    List columns = GetSelectColumn(schema);

    cmd.CommandText = string.Format(
        "Select {0} From {1}{2}",
        string.Join(",",
            columns.ConvertAll(
                GetColumnExpression).ToArray()),
        GetTableExpression(schema),
        b.QueryText);

    cmd.Parameters.AddRange(b.Parameters.ToArray());
    return cmd;
}

protected virtual List GetSelectColumn(DataTable schema)
{
    List columns = new List();
    foreach (DataColumn column in schema.Columns)
    {
        columns.Add(column);
    }
    return columns;
}

UPDATE文やINSERT文もほぼ同様に作成することになりますが、ただ、今回はRoRのような特定のカラムを導入することで決まった処理が簡単にできる仕組みを導入するようにします。導入する組み込みカラムはLockVersion、UpdatedAt、CreatedAtの3つで、最初のLockVersionは楽観ロック用で後の2つはタイムスタンプ用です。
また、SQL ServerのInsertは自動採番の仕組みがあるので採番した値を取得することも可能にすようにします。
発行されるSQL文の例は以下のような感じです。

Update [Salary] Set [EmployeeID]=@EmployeeID,[Amount]=@Amount,[IssueDate]=@IssueDate,
 [LockVersion]=[LockVersion]+1,[UpdatedAt]=GETDATE() 
 Where [ID]=@ID And [LockVersion]=@LockVersion
Insert Into [Salary] ([EmployeeID],[Amount],[IssueDate],[LockVersion],[CreatedAt]) Values
 (@EmployeeID,@Amount,@IssueDate,0,GETDATE());
Select [ID] From [Salary] Where ([ID]=@@IDENTITY)

余談ですが、独自フレームワークを作成した場合の良し悪しはいろいろありますが、SQL文の生成パターンをコントロールできる点は非常に拡張性のメリットがあると感じています。

つづく

追記

今回フレームワークのコードを作成しながら日記も書いていこう考えていましたが、コード作成のほうが思いのほか進んでほぼ完了してしまいました。今回の楽観ロック用のカラムの実装は実際は一番最後に追加した機能です。もう少しリアルに近い手順で機能追加するようなストーリのほうが良いかなと考えたのですが、削るのも手間なので今回書いてしまいました。