using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Common; using ScrewTurn.Wiki.PluginFramework; namespace ScrewTurn.Wiki.Plugins.SqlCommon { /// /// Implements a base class for all SQL-based classes. /// public abstract class SqlClassBase { #region Utility Methods /// /// Gets a value indicating whether a column contains nonexistent or missing value. /// /// The . /// The name of the column. /// true if the column contains a nonexistent or missing value, false otherwise. protected bool IsDBNull(DbDataReader reader, string column) { return reader.IsDBNull(reader.GetOrdinal(column)); } /// /// Gets the value of a nullable column. /// /// The return type. /// The . /// The name of the column. /// The default value to return when the column contains a null value. /// The value. protected T GetNullableColumn(DbDataReader reader, string column, T defaultValue) { if(IsDBNull(reader, column)) return defaultValue; else return (T)reader[column]; } /// /// Reads all the contents of a binary column. /// /// The . /// The name of the column. /// The max size, in bytes, to read. If exceeded, null is returned. /// The read bytes, or null. /// This method buffers the data in memory; avoid reading data bigger than a few megabytes. protected byte[] GetBinaryColumn(DbDataReader reader, string column, int maxSize) { // 128 KB read buffer byte[] buffer = new byte[131072]; byte[] tempResult = new byte[maxSize]; int columnOrdinal = reader.GetOrdinal(column); long read = 0; long totalRead = 0; do { read = reader.GetBytes(columnOrdinal, totalRead, buffer, 0, buffer.Length); if(totalRead + read > maxSize) return null; if(read > 0) { Buffer.BlockCopy(buffer, 0, tempResult, (int)totalRead, (int)read); } totalRead += read; } while(read > 0); // Copy tempBuffer in final array buffer = null; byte[] result = new byte[totalRead]; Buffer.BlockCopy(tempResult, 0, result, 0, result.Length); return result; } /// /// Copies all the contents of a binary column into a . /// /// The . /// The name of the column. /// The destination . protected int ReadBinaryColumn(DbDataReader reader, string column, System.IO.Stream stream) { // 128 KB read buffer byte[] buffer = new byte[131072]; int columnOrdinal = reader.GetOrdinal(column); int read = 0; int totalRead = 0; do { read = (int)reader.GetBytes(columnOrdinal, totalRead, buffer, 0, buffer.Length); if(read > 0) { stream.Write(buffer, 0, read); } totalRead += read; } while(read > 0); return totalRead; } /// /// Logs an exception. /// /// The exception. protected abstract void LogException(Exception ex); /// /// Executes a scalar command, then closes the connection. /// /// The return type. /// The command to execute. /// The default value of the return value, to use when the command fails. /// The result. /// The connection is closed after the execution. protected T ExecuteScalar(DbCommand command, T defaultValue) { return ExecuteScalar(command, defaultValue, true); } /// /// Executes a scalar command, then closes the connection. /// /// The return type. /// The command to execute. /// The default value of the return value, to use when the command fails. /// A value indicating whether to close the connection after execution. /// The result. protected T ExecuteScalar(DbCommand command, T defaultValue, bool close) { object temp = null; try { temp = command.ExecuteScalar(); } catch(DbException dbex) { LogException(dbex); } finally { if(close) { CloseConnection(command.Connection); } } if(temp != null) { return (T)temp; } else return defaultValue; } /// /// Executes a non-query command, then closes the connection. /// /// The command to execute. /// The rows affected (-1 if the command failed). /// The connection is closed after the execution. protected int ExecuteNonQuery(DbCommand command) { return ExecuteNonQuery(command, true); } /// /// Executes a non-query command, then closes the connection if requested. /// /// The command to execute. /// A value indicating whether to close the connection after execution. /// The rows affected (-1 if the command failed). protected int ExecuteNonQuery(DbCommand command, bool close) { return ExecuteNonQuery(command, close, true); } /// /// Executes a non-query command, then closes the connection if requested. /// /// The command to execute. /// A value indicating whether to close the connection after execution. /// A value indicating whether to log any error. /// The rows affected (-1 if the command failed). protected int ExecuteNonQuery(DbCommand command, bool close, bool logError) { int rows = -1; try { rows = command.ExecuteNonQuery(); } catch(DbException dbex) { if(logError) LogException(dbex); } finally { if(close) { CloseConnection(command.Connection); } } return rows; } /// /// Executes a reader command, leaving the connection open. /// /// The command to execute. /// A value indicating whether to close the connection on error. /// The data reader, or null if the command fails. protected DbDataReader ExecuteReader(DbCommand command, bool closeOnError) { DbDataReader reader = null; try { reader = command.ExecuteReader(); } catch(DbException dbex) { LogException(dbex); if(closeOnError) CloseConnection(command.Connection); } return reader; } /// /// Executes a reader command, leaving the connection open. /// /// The command to execute. /// The data reader, or null if the command fails. /// If the command fails, the connection is closed. protected DbDataReader ExecuteReader(DbCommand command) { return ExecuteReader(command, true); } /// /// Closes a connection, swallowing all exceptions. /// /// The connection to close. protected void CloseConnection(DbConnection connection) { try { connection.Close(); } catch { } } /// /// Closes a reader, a command and the associated connection. /// /// The command. /// The reader. protected void CloseReader(DbCommand command, DbDataReader reader) { try { reader.Close(); } catch { } CloseConnection(command.Connection); } /// /// Closes a reader. /// /// The reader. protected void CloseReader(DbDataReader reader) { try { reader.Close(); } catch { } } /// /// Begins a transaction. /// /// The connection. /// The transaction. protected DbTransaction BeginTransaction(DbConnection connection) { return connection.BeginTransaction(); } /// /// Commits a transaction. /// /// The transaction. protected void CommitTransaction(DbTransaction transaction) { // Commit sets transaction.Connection to null DbConnection connection = transaction.Connection; transaction.Commit(); transaction.Dispose(); CloseConnection(connection); } /// /// Rolls back a transaction. /// /// The transaction. protected void RollbackTransaction(DbTransaction transaction) { // Rollback sets transaction.Connection to null DbConnection connection = transaction.Connection; try { transaction.Rollback(); } catch { } transaction.Dispose(); CloseConnection(connection); } #endregion } }