LoginSignup
0
0

More than 3 years have passed since last update.

NPocoの紹介 -カスタマイズ編- 空文字列をnullに変換して登録する

Posted at

NPocoの紹介 -カスタマイズ編- 空文字列をnullに変換して登録する

最初の記事はこちら

今回はカスタマイズ方法についての紹介です。

注意

このカスタマイズ方法は公式で紹介されているものではなく、私が独自で行っているものです。

あらかじめご注意ください。

やること

InsertやUpdateにおいてパラメータに空文字列が含まれていた場合、これをnullに変換して登録する。
(「複数DBベンダー対応をする際にOracleの挙動に合わせるため」 などが動機として考えられます。
というか私はそれでした😀)

方法1 Database クラスの AddParameter をオーバーライドする。

一つ目の方法は Database クラスそのものを継承し、AddParameter クラスの挙動を変更します。

MyDatabase.cs
public class MyDatabase : Database
{
    public MyDatabase(DbConnection connection) : base(connection) { }

    public override void AddParameter(DbCommand cmd, object value)
    {
        if (value is string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                //空文字列ならnullで親のメソッドを呼ぶ
                base.AddParameter(cmd, null);
                return;
            }
        }
        //それ以外はそのまま
        base.AddParameter(cmd, value);
    }
}

実行コード

using MyDatabase database = new MyDatabase(con);
database.Insert(new Emp
{
    EmpId = "EX01",
    FirstName = "",
    FamilyName = "",
    DeptCode = "X01",
    CreatedAt = new DateTime(2020, 6, 30),
    UpdatedAt = new DateTime(2020, 6, 30),
});

実行ログ

INSERT INTO "emp" ("emp_id","first_name","family_name","dept_code","created_at","updated_at") VALUES (@p0,@p1,@p2,@p3,@p4,@p5)
         -> @p0 [String] = "EX01"
         -> @p1 [DBNull] = ""
         -> @p2 [DBNull] = ""
         -> @p3 [String] = "X01"
         -> @p4 [DateTime] = "2020/06/30 0:00:00"
         -> @p5 [DateTime] = "2020/06/30 0:00:00"

p1, p2が[DBNull] となっていることからnull で登録されていることが確認できます。

方法2 IMapperGetParameterConverter を使用する。

IMapper というインターフェースが用意されており、これを利用すると、データベースから結果を取り出すときや、データベースへ登録するときに 変換処理などを行うことが可能です。

今回はこのIMapperGetParameterConverter メソッドを利用します。

このメソッドは前述のDatabase.AddParameter で実行されています。

またIMapper を直接実装するのではなく、あらかじめ用意されたDefaultMapperを継承して作成します。

MyMapper.cs
public class MyMapper : DefaultMapper
{
    private readonly IDictionary<Type, Func<object, object>> _converters = new Dictionary<Type, Func<object, object>>
    {
        [typeof(string)] = s => string.IsNullOrEmpty((string)s) ? null : s,
    };


    public override Func<object, object> GetParameterConverter(DbCommand dbCommand, Type sourceType)
    {
        if (_converters.TryGetValue(sourceType, out Func<object, object> converter))
        {
            return converter;
        }
        return base.GetParameterConverter(dbCommand, sourceType);
    }
}

実行コード

using Database database = new Database(con);
database.Mappers.Add(new MyMapper());

database.Insert(new Emp
{
    EmpId = "EX01",
    FirstName = "",
    FamilyName = "",
    DeptCode = "X01",
    CreatedAt = new DateTime(2020, 6, 30),
    UpdatedAt = new DateTime(2020, 6, 30),
});

実行ログ

INSERT INTO "emp" ("emp_id","first_name","family_name","dept_code","created_at","updated_at") VALUES (@p0,@p1,@p2,@p3,@p4,@p5)
         -> @p0 [String] = "EX01"
         -> @p1 [DBNull] = ""
         -> @p2 [DBNull] = ""
         -> @p3 [String] = "X01"
         -> @p4 [DateTime] = "2020/06/30 0:00:00"
         -> @p5 [DateTime] = "2020/06/30 0:00:00"

Database.AddParameter と同様の結果になっています。

注意点

これらの方法ですが、全てのパラメータマッピング時に実行されるため、SELECTを実行する場合でも呼び出されてしまいます。
(アプリの仕様によってはこれが害になる可能性もあります。)

またSELECT + INSERT, SELECT + UPDATE のようなパラメータを介さないものについてはこれらのメソッドが実行されてないので、変換は行われません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0