ゆるふわエンジニアのブログ

行ったこと、調べたこと等をつらつらと書いていくかもしれません。

Dapperを触ってみた(導入、簡単な操作編)(Micro-ORM)

簡単にDBを操作できるライブラリを探している中で、
Dapperを見つけ触ってみたので、記事として残しておきます。

用途としては、EntityFrameworkと併用することが多いみたいですね。
EntityFrameworkでいけるところはEntityFrameworkを使用し、
手の届かない痒いところはDapperで対応する。といった感じでしょうか。
あ、サンプルの言語はC#です。

お品書き

Dapperとは

以下URLに載っていることを読んでください。(丸投げ)
GitHub - StackExchange/Dapper: Dapper - a simple object mapper for .Net

インストール方法

以下のコマンドをパッケージマネージャコンソールで実行するだけです。
簡単!

Install-Package Dapper

簡単な操作方法

コネクション作って、App.configの情報を元に接続して、
トランザクション開始して、各操作を行い、
最後に接続を切断しています。
Insert、Update、Deleteは、上記以外にコミット、ロールバックを行っていますね。
例外が発生しなければコミット、
例外が発生したらロールバックという実装にしています。

使用しているEntityクラス

クラス名はテーブル名と同じ、
プロパティ名は列名と同じにしてあります。

class USER_MASTER
{
    public string USER_ID { get; set; }
    public string DEPT_NO { get; set; }
    public string USER_NAME { get; set; }
    public DateTime? CREATED_ON { get; set; }
    public DateTime? MODIFIED_ON { get; set; }

    // プロパティの値確認用
    public override string ToString()
    {
        var retStr = new StringBuilder();
        retStr.AppendFormat("USER_ID:{0}\t", this.USER_ID);
        retStr.AppendFormat("DEPT_NO:{0}\t", this.DEPT_NO);
        retStr.AppendFormat("USER_NAME:{0}\t", this.USER_NAME);
        retStr.AppendFormat("CREATED_ON:{0}\t", this.CREATED_ON);
        retStr.AppendFormat("MODIFIED_ON:{0}\t", this.MODIFIED_ON);
        return retStr.ToString();
    }
}

Select

// プロバイダの情報を取得
var provider = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings[connectionName].ProviderName);
// 接続情報取得
using (var connection = provider.CreateConnection())
{
    // 接続文字列をApp.configから取得し設定
    connection.ConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            // Select文作成
            var sql = @"SELECT * FROM USER_MASTER WHERE USER_ID = :USER_ID";
            // バインド変数用インスタンス作成
            var bindObj = new USER_MASTER() { USER_ID = "0001" };
            // Select文実行
            var rows = connection.Query<USER_MASTER>(sql, bindObj, transaction);
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Insert

// プロバイダの情報を取得
var provider = DbProviderFactories.GetFactory(ConfigurationManager.ConnectionStrings[connectionName].ProviderName);
// 接続情報取得
using (var connection = provider.CreateConnection())
{
    // 接続文字列をApp.configから取得し設定
    connection.ConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
    try
    {
        // 接続開始
        connection.Open();
        // トランザクション開始
        using (var transaction = connection.BeginTransaction())
        {
            try
            {
                // Insert文作成
                var sql = @"INSERT INTO USER_MASTER ( USER_ID, DEPT_NO ) VALUES ( :USER_ID, :DEPT_NO )";
                // Insert用インスタンス作成
                var insertObj = new USER_MASTER() { USER_ID = "9999", DEPT_NO = "9999" };
                // Insert文実行
                var result = connection.Execute(sql, insertObj, transaction);
                // コミット
                transaction.Commit();
            }
            catch
            {
                // ロールバック
                transaction.Rollback();
                throw;
            }
        }
    }
    finally
    {
        // 接続切断
        connection.Close();
    }
}

Update

接続やトランザクション周りはInsertと同じなので割愛。

// コネクションやトランザクション関係の前処理(省略)
// Update文作成
var sql = @"UPDATE USER_MASTER SET USER_NAME = :USER_NAME WHERE USER_ID = :USER_ID";
// Update用インスタンス作成
var updateObj = new USER_MASTER() { USER_ID = "9999", USER_NAME = "HOGE" };
// Update文実行
var result = connection.Execute(sql, updateObj, transaction);
// コネクションやトランザクション関係の後処理(省略)

Delete

// コネクションやトランザクション関係の前処理(省略)
// Update文作成
var sql = @"DELETE FROM USER_MASTER WHERE USER_ID = :USER_ID";
// Delete用インスタンス作成
var deleteObj = new USER_MASTER() { USER_ID = "9999"};
// Update文実行
var result = connection.Execute(sql, deleteObj, transaction);
// コネクションやトランザクション関係の後処理(省略)


各DBに依存せず使用できそうですし、簡単に使用できて良いですね。
でも、毎回コネクションやトランザクション関係のお決まりとなっているコードを
書くのは非常につらいので、これらはフレームワーク化(ライブラリ化)し、
隠蔽してやる必要がありそうです。