using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data; using System.Data.Common; using System.IO; namespace PkmnFoundations.Data { /// /// Provides extension and convenience methods for working with ADO.NET databases. /// public static class DatabaseExtender { #region Command Execution /// /// Runs a command and returns a DataTable containing its results. /// /// Command already initialized with an open connection public static DataTable ExecuteDataTable(this DbCommand cmd) { IDataReader reader = cmd.ExecuteReader(); DataTable result = new DataTable(); result.Load(reader); return result; } /// /// Runs a command and returns a DataTable containing its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static DataTable ExecuteDataTable(this DbConnection db, String sqlstr, params IDataParameter[] _params) { IDataReader reader = db.ExecuteReader(sqlstr, _params); DataTable result = new DataTable(); result.Load(reader); return result; } /// /// Runs a command and returns a DataTable containing its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static DataTable ExecuteDataTable(this DbConnection db, String sqlstr, IEnumerable _params) { IDataReader reader = db.ExecuteReader(sqlstr, _params.ToArray()); DataTable result = new DataTable(); result.Load(reader); return result; } /// /// Runs a command and returns a DataTable containing its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static DataTable ExecuteDataTable(this DbTransaction tran, String sqlstr, params IDataParameter[] _params) { IDataReader reader = tran.ExecuteReader(sqlstr, _params); DataTable result = new DataTable(); result.Load(reader); return result; } /// /// Runs a command and returns a DataTable containing its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static DataTable ExecuteDataTable(this DbTransaction tran, String sqlstr, IEnumerable _params) { IDataReader reader = tran.ExecuteReader(sqlstr, _params.ToArray()); DataTable result = new DataTable(); result.Load(reader); return result; } /// /// Runs a command and returns a reader that iterates its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static IDataReader ExecuteReader(this DbConnection db, String sqlstr, params IDataParameter[] _params) { // hooray DbConnection provides a command factory DbCommand cmd = db.CreateCommand(); cmd.CommandText = sqlstr; // fixme: catch "System.ArgumentException: The SqlParameter is already contained // by another SqlParameterCollection." and add a clone instead cmd.Parameters.AddRange(_params); return cmd.ExecuteReader(); } /// /// Runs a command and returns a reader that iterates its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static IDataReader ExecuteReader(this DbConnection db, String sqlstr, IEnumerable _params) { return db.ExecuteReader(sqlstr, _params.ToArray()); } /// /// Runs a command and returns a reader that iterates its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static IDataReader ExecuteReader(this DbTransaction tran, String sqlstr, params IDataParameter[] _params) { // hooray DbConnection provides a command factory DbCommand cmd = tran.Connection.CreateCommand(); cmd.CommandText = sqlstr; cmd.Transaction = tran; cmd.Parameters.AddRange(_params); return cmd.ExecuteReader(); } /// /// Runs a command and returns a reader that iterates its results. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static IDataReader ExecuteReader(this DbTransaction tran, String sqlstr, IEnumerable _params) { return tran.ExecuteReader(sqlstr, _params.ToArray()); } /// /// Runs a command and returns the first column of the first row in the query. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static object ExecuteScalar(this DbConnection db, String sqlstr, params IDataParameter[] _params) { DbCommand cmd = db.CreateCommand(); cmd.CommandText = sqlstr; cmd.Parameters.AddRange(_params); return cmd.ExecuteScalar(); } /// /// Runs a command and returns the number of rows affected, subject to the usual quirkiness of ExecuteNonQuery. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static int ExecuteNonQuery(this DbConnection db, String sqlstr, params IDataParameter[] _params) { DbCommand cmd = db.CreateCommand(); cmd.CommandText = sqlstr; cmd.Parameters.AddRange(_params); return cmd.ExecuteNonQuery(); } /// /// Runs a command and returns the first column of the first row in the query. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static object ExecuteScalar(this DbTransaction tran, String sqlstr, params IDataParameter[] _params) { DbCommand cmd = tran.Connection.CreateCommand(); cmd.CommandText = sqlstr; cmd.Transaction = tran; cmd.Parameters.AddRange(_params); return cmd.ExecuteScalar(); } /// /// Runs a command and returns the number of rows affected, subject to the usual quirkiness of ExecuteNonQuery. /// /// Open data connection /// SQL string /// List of parameters to use with the SQL public static int ExecuteNonQuery(this DbTransaction tran, String sqlstr, params IDataParameter[] _params) { DbCommand cmd = tran.Connection.CreateCommand(); cmd.CommandText = sqlstr; cmd.Transaction = tran; cmd.Parameters.AddRange(_params); return cmd.ExecuteNonQuery(); } #endregion #region DataReader convenience /// /// Obtains a string value or returns a default value if null. /// /// Active reader with data /// Column ordinal /// Default value /// public static String GetStringOrDefault(this IDataReader reader, int column, String _default) { return reader.IsDBNull(column) ? _default : reader.GetString(column); } /// /// Obtains a string value or returns an empty string if null. /// /// Active reader with data /// Column ordinal /// public static String GetStringOrDefault(this IDataReader reader, int column) { return reader.IsDBNull(column) ? "" : reader.GetString(column); } /// /// Obtains a string value or returns a default value if null. /// /// Active reader with data /// Column name /// Default value /// public static String GetStringOrDefault(this IDataReader reader, String column, String _default) { return (reader[column] is DBNull) ? _default : (String)reader[column]; } /// /// Obtains a string value or returns an empty string if null. /// /// Active reader with data /// Column name /// public static String GetStringOrDefault(this IDataReader reader, String column) { return (reader[column] is DBNull) ? "" : (String)reader[column]; } public static void GetBytes(this IDataReader reader, String column, long fieldOffset, byte[] buffer, int bufferOffset, int length) { reader.GetBytes(reader.GetOrdinal(column), fieldOffset, buffer, bufferOffset, length); } public static byte[] GetByteArray(this IDataReader reader, int column) { // optimized version of http://msdn.microsoft.com/en-us/library/87z0hy49%28v=vs.110%29.aspx MemoryStream m = new MemoryStream(); const int BUFFER_LENGTH = 256; byte[] buffer = new byte[BUFFER_LENGTH]; long progress = 0; long lastProgress; do { lastProgress = reader.GetBytes(column, progress, buffer, 0, BUFFER_LENGTH); m.Write(buffer, 0, (int)lastProgress); progress += lastProgress; } while (lastProgress == BUFFER_LENGTH); m.Flush(); return m.GetBuffer(); } public static byte[] GetByteArray(this IDataReader reader, int column, int length) { byte[] result = new byte[length]; reader.GetBytes(column, 0, result, 0, length); return result; } public static byte[] GetByteArray(this IDataReader reader, String column) { return GetByteArray(reader, reader.GetOrdinal(column)); } public static byte[] GetByteArray(this IDataReader reader, String column, int length) { return GetByteArray(reader, reader.GetOrdinal(column), length); } public static bool IsDBNull(this IDataReader reader, String column) { return reader.IsDBNull(reader.GetOrdinal(column)); } #endregion public static T Cast(object value) { if (value is DBNull) return default(T); return (T)value; } } }