SQLite のヘルパー関数 (C#)

プログラミング

SQLiteのヘルパークラス(C#)を作成(改良)したので、アップします。

SQLiteの紹介

SQLiteはMySQLと同じデータベース管理システムです。
サーバとしてではなくアプリケーションに組み込んで利用される軽量のデータベースです。
データは単一のファイルに書き込まれるので、バックアップやリストアはファイルコピーで行えるお手軽さがあります。

System.Data.SQLiteの紹介

System.Data.SQLiteはSQLiteに接続や開発するための.NETライブラリです。
ライブラリを追加するだけで開発者はSQLiteの操作を意識せずに開発することができます。

ヘルパークラスの公開

作成したクラスは、以下で公開されているソースを改良したものです。
http://d.hatena.ne.jp/mftech/20100929/1285754844

特に、複数レコードのInsert処理を楽に行えるようにしています。
レコードは、配列やコレクションとして渡すことが出来ます。

テストコードも含まれているプロジェクトファイルをここからダウンロードできます。

namespace MyTools
{
    /// <summary>
    /// 機能: SQLite データベース処理の共通クラス
    /// 作成者: 2010-04-01 zhoufoxcn(周公) 
    ///          2011-10-12 Estable
    /// Blog: http://zhoufoxcn.blog.51cto.com or http://blog.csdn.net/zhoufoxcn
    /// 参考: http://d.hatena.ne.jp/mftech/20100929/1285754844
    ///        http://blogs.wankuma.com/hatsune/archive/2008/10/16/158915.aspx
    /// </summary>
    public class SQLiteHelper
    {
        private string databasePath = string.Empty;
        private string connectionString = string.Empty;

        
        /// <summary>
        /// コンストラクタ。データベースファイルパスを設定する。
        /// </summary>
        /// <param name="dbPath">データベースの接続パス</param>
        public SQLiteHelper(string dbPath, params string[] options)
        {
            this.databasePath = dbPath;
            this.connectionString = "Data Source=" + dbPath;
            if (options != null && options.Length > 0)
            {
                this.connectionString += ";" + string.Join(";", options);
            }
        }


        /// <summary>
        /// データベースファイルが存在するかの bool 値を返す。
        /// </summary>
        /// <returns>True:存在する, False:存在しない</returns>
        public bool ExistDBFile()
        {
            if (System.IO.File.Exists(this.databasePath))
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        /// <summary>
        /// データベースを新規作成
        /// </summary>
        /// <returns>True:作成した or 既に存在する,  False:作成出来なかった</returns>
        public bool CreateDB()
        {
            using (SQLiteConnection connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                connection.Close();
            }

            return ExistDBFile();
        }


        /// <summary>
        /// データベースを削除
        /// </summary>
        /// <returns>True:削除した or 既に存在しない,  False:削除出来なかった</returns>
        public bool DeleteDBFile()
        {
            try
            {
                System.IO.File.Delete(databasePath);
            }
            catch { }

            return !ExistDBFile();
        }


        /// <summary>
        /// テーブルが存在するかの bool 値を返す。
        /// </summary>
        /// <param name="tableName">テーブル名</param>
        /// <returns>True:存在する, False:存在しない</returns>
        public bool ExistTable(string tableName)
        {
            // データベースファイルが無ければ 例外
            if (!ExistDBFile()) throw new SQLiteException(SQLiteErrorCode.CantOpen, "database file is not found");

            // システムテーブルからテーブル名を検索する
            var sql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=@name";
            var parameters = new SQLiteParameter[] {
                new SQLiteParameter("@name", tableName),
            };

            var o = this.ExecuteScalar(sql, parameters);
            var i = (o is IConvertible) ? Convert.ToInt32(o, CultureInfo.InvariantCulture) : 0;

            return (bool)(i > 0);
        }


        /// <summary>
        /// For a given intrinsic type, return a DbType
        /// </summary>
        /// <param name="typ">The native type to convert</param>
        /// <returns>The corresponding (closest match) DbType</returns>
        public static DbType TypeToDBType(Type typ)
        {
            TypeCode tc = Type.GetTypeCode(typ);
            if (tc == TypeCode.Object)
            {
                if (typ == typeof(byte[])) return DbType.Binary;
                if (typ == typeof(Guid)) return DbType.Guid;
                return DbType.String;
            }
            DbType[] _typetodbtype = 
              { DbType.Object,  DbType.Binary,   DbType.Object, DbType.Boolean, DbType.SByte,
                DbType.SByte,   DbType.Byte,     DbType.Int16,  DbType.UInt16,  DbType.Int32,
                DbType.UInt32,  DbType.Int64,    DbType.UInt64, DbType.Single,  DbType.Double,
                DbType.Decimal, DbType.DateTime, DbType.Object, DbType.String, };
            return _typetodbtype[(int)tc];
        }


        /// <summary>
        /// レコードを追加・削除する SQL 文を実行し、影響行数を返す。
        /// </summary>
        /// <param name="sql">実行用の SQL 文</param>
        /// <param name="parameters">SQL 実行用の引数</param>
        /// <returns>SQL により影響を受けた行数</returns>
        public int ExecuteNonQuery(string sql)
        {
            return ExecuteNonQuerys(sql, null);
        }

        public int ExecuteNonQuery(string sql, params object[] parameters)
        {
            if (parameters != null && parameters.Count() == 1 && parameters[0] is Array)
            {
                return ExecuteNonQuerys(sql, new List<IEnumerable<object>> { (IEnumerable<object>)parameters[0], });
            }
            else
            {
                return ExecuteNonQuerys(sql, new List<IEnumerable<object>> { parameters, });
            }
        }

        public int ExecuteNonQuerys(string sql, IEnumerable<IEnumerable<object>> parameters)
        {
            int affectedRows = 0;

            using (var connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                using (var transaction = connection.BeginTransaction())
                {
                    using (var command = new SQLiteCommand(sql, connection))
                    {
                        if (parameters != null && parameters.Count() != 0)
                        {
                            foreach (var p in parameters)
                            {
                                command.Parameters.Clear();
                                if (p != null && p.Count() != 0)
                                {
                                    var paramNormalize = p.Select(x =>
                                    {
                                        if (x == null || x is Array)
                                        {
                                            return new SQLiteParameter();
                                        }
                                        else if (x.GetType() == typeof(SQLiteParameter))
                                        {
                                            return (SQLiteParameter)x;
                                        }
                                        else
                                        {
                                            return new SQLiteParameter(TypeToDBType(x.GetType()), x);
                                        }
                                    }).ToArray();
                                    command.Parameters.AddRange(paramNormalize);
                                }      
                                affectedRows += command.ExecuteNonQuery();
                            }
                        }
                        else
                        {
                            affectedRows += command.ExecuteNonQuery();
                        }
                    }
                    transaction.Commit();
                }
            }
            return affectedRows;
        }


        /// <summary>
        /// SQL 文を実行し、検索結果が格納される DataReader を返す
        /// </summary>
        /// <param name="sql">実行用の SQL 文</param>
        /// <param name="parameters">SQL 実行用の引数</param>
        /// <returns>検索結果を読取る SQLiteDataReader</returns>
        public SQLiteDataReader ExecuteReader(string sql)
        {
            return ExecuteReader(sql, null);
        }

        public SQLiteDataReader ExecuteReader(string sql, params object[] parameters)
        {
            if (parameters != null && parameters.Count() == 1 && parameters[0] is Array)
            {
                return ExecuteReader(sql, (IEnumerable<object>)parameters[0]);
            }
            else
            {
                return ExecuteReader(sql, (IEnumerable<object>)parameters);
            }
        }

        public SQLiteDataReader ExecuteReader(string sql, IEnumerable<object> parameters)
        {
            var connection = new SQLiteConnection(connectionString);
            var command = new SQLiteCommand(sql, connection);

            if (parameters != null && parameters.Count() != 0)
            {
                var paramNormalize = parameters.Select(x =>
                {
                    if (x == null || x is Array)
                    {
                        return new SQLiteParameter();
                    }
                    else if (x.GetType() == typeof(SQLiteParameter))
                    {
                        return (SQLiteParameter)x;
                    }
                    else
                    {
                        return new SQLiteParameter(TypeToDBType(x.GetType()), x);
                    }
                }).ToArray();
                command.Parameters.AddRange(paramNormalize);
            }

            connection.Open();
            var reader = command.ExecuteReader(CommandBehavior.CloseConnection);
            return reader;
        }


        /// <summary>
        /// SQL 文を実行し、検索結果が格納される DataTable を返す
        /// </summary>
        /// <param name="sql">実行用の SQL 文</param>
        /// <param name="parameters">SQL 実行用の引数</param>
        /// <returns>検索結果を格納した DataTable</returns>
        public DataTable ExecuteDataTable(string sql)
        {
            return ExecuteDataTable(sql, null);
        }

        public DataTable ExecuteDataTable(string sql, params object[] parameters)
        {
            if (parameters != null && parameters.Count() == 1 && parameters[0] is Array)
            {
                return ExecuteDataTable(sql, (IEnumerable<object>)parameters[0]);
            }
            else
            {
                return ExecuteDataTable(sql, (IEnumerable<object>)parameters);
            }
        }
       
        public DataTable ExecuteDataTable(string sql, IEnumerable<object> parameters)
        {
            using (var connection = new SQLiteConnection(connectionString))
            {
                using (var command = new SQLiteCommand(sql, connection))
                {
                    if (parameters != null && parameters.Count() != 0)
                    {
                        var paramNormalize = parameters.Select(x =>
                        {
                            if (x == null || x is Array)
                            {
                                return new SQLiteParameter();
                            }
                            else if (x.GetType() == typeof(SQLiteParameter))
                            {
                                return (SQLiteParameter)x;
                            }
                            else
                            {
                                return new SQLiteParameter(TypeToDBType(x.GetType()), x);
                            }
                        }).ToArray();
                        command.Parameters.AddRange(paramNormalize);
                    }

                    var adapter = new SQLiteDataAdapter(command);
                    var data = new DataTable();
                    data.Locale = CultureInfo.InvariantCulture;
                    adapter.Fill(data);
                    return data;
                }
            }
        
        
        }


        /// <summary>
        /// SQL 文を実行し、検索結果の第1行第1列を返す
        /// </summary>
        /// <param name="sql">実行用の SQL 文</param>
        /// <param name="parameters">SQL 実行用の引数</param>
        /// <returns>取得結果の値</returns>
        public object ExecuteScalar(string sql)
        {
            return ExecuteScalar(sql, null);
        }

        public object ExecuteScalar(string sql, params object[] parameters)
        {
            if (parameters != null && parameters.Count() == 1 && parameters[0] is Array)
            {
                return ExecuteScalar(sql, (IEnumerable<object>)parameters[0]);
            }
            else
            {
                return ExecuteScalar(sql, (IEnumerable<object>)parameters);
            }
        }

        public object ExecuteScalar(string sql, IEnumerable<object> parameters)
        {
            using (var connection = new SQLiteConnection(connectionString))
            {
                using (var command = new SQLiteCommand(sql, connection))
                {
                    if (parameters != null && parameters.Count() != 0)
                    {
                        var paramNormalize = parameters.Select(x =>
                        {
                            if (x == null || x is Array)
                            {
                                return new SQLiteParameter();
                            }
                            else if (x.GetType() == typeof(SQLiteParameter))
                            {
                                return (SQLiteParameter)x;
                            }
                            else
                            {
                                return new SQLiteParameter(TypeToDBType(x.GetType()), x);
                            }
                        }).ToArray();
                        command.Parameters.AddRange(paramNormalize);
                    }

                    connection.Open();
                    return command.ExecuteScalar();
                }
            }
        
        }


        /// <summary>
        /// データ型情報の取得
        /// </summary>
        /// <returns></returns>
        public DataTable GetSchema()
        {
            using (SQLiteConnection connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                DataTable data = connection.GetSchema("TABLES");
                connection.Close();
                return data;
            }
        }

    }
}

コメント