読者です 読者をやめる 読者になる 読者になる

Dapper.SqlBuilderに機能を追加してみる

Dapper.SqlBuilderはシンプルながら便利なライブラリです。

mrgchr.hatenablog.com

今回は独自機能を追加してみようと思います。

Dapper.SqlBuilderのソースコードは下記の通りです。
1ファイルのみの非常にシンプルなライブラリです。

github.com

読んでみると、SQLの各句に相当するメソッドは下記のAddClauseメソッドを呼んでいます。

protected void AddClause(string name, string sql, object parameters, string joiner, string prefix = "", string postfix = "", bool isInclusive = false)
{
  Clauses clauses;
  if (!_data.TryGetValue(name, out clauses))
  {

が、このAddClauseメソッド、protectedです。
拡張メソッドで機能拡張しようと思っていたのですが、そうもいかなくなりました。

個人的にはあまり好きではないのですが、しょうがないので継承します。

public class MySqlBuilder : SqlBuilder
{
  public MySqlBuilder() : base()
  {

  }

  public MySqlBuilder Set(string sql, dynamic parameters = null)
  {
    AddClause("set", sql, parameters, " , ", "Set ", "\n", false);
    return this;
  }
}

今回は、UPDATE分のSETを組み立てるメソッドを作ってみました。

この新しいビルダーを使うことで、下記のように更新が必要なフィールドのみを更新するクエリを簡単に組み立てられるようになります。

var updateSql =
$@"
UPDATE TodoItems
/**set**/
Where [Id] = @{nameof(itemId)};
";

var builder = new MySqlBuilder();
var updateTemplate = builder.AddTemplate(updateSql);

var param = new DynamicParameters();
param.Add(nameof(itemId), itemId);

if(isDone.HasValue)
{
  builder.Set($@"[Done] = @{nameof(isDone)}");
  param.Add(nameof(isDone), isDone);
}
      
if(!string.IsNullOrEmpty(title))
{
  builder.Set($@"[Title] = @{nameof(title)}");
  param.Add(nameof(title), title);
} 

using (var conn = new SqlConnection(connectionstring))
{
  var result = conn.Execute(updateTemplate.RawSql, param);
}

本題ではないのですが、builder.Set()を一度も呼ばないパスだとエラーになります。当然ですね。
それと文字列型の更新可否をstring.IsNullOrEmptyで判断してしまうと、空文字クリアができなくなります。Option型が欲しくなりますよね。