//******************************************************************************************************
// AdoDataConnection.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 04/07/2011 - J. Ritchie Carroll
// Generated original version of source code.
// 09/19/2011 - Stephen C. Wills
// Added database awareness and Oracle database compatibility.
// 10/18/2011 - J. Ritchie Carroll
// Modified ADO database class to allow directly instantiated instances, as well as configured.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using GSF.Annotations;
using GSF.Configuration;
namespace GSF.Data
{
///
/// Specifies the database type underlying an .
///
public enum DatabaseType
{
///
/// Underlying ADO database type is Microsoft Access.
///
Access,
///
/// Underlying ADO database type is SQL Server.
///
SQLServer,
///
/// Underlying ADO database type is MySQL.
///
MySQL,
///
/// Underlying ADO database type is Oracle.
///
Oracle,
///
/// Underlying ADO database type is SQLite.
///
SQLite,
///
/// Underlying ADO database type is PostgreSQL.
///
PostgreSQL,
///
/// Underlying ADO database type is unknown.
///
Other
}
///
/// Creates a new from any specified or configured ADO.NET data source.
///
///
/// Example connection and data provider strings:
///
///
/// Database type
/// Example connection string / data provider string
///
/// -
/// SQL Server
///
/// ConnectionString = "Data Source=serverName; Initial Catalog=databaseName; User ID=userName; Password=password"
/// DataProviderString = "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.SqlClient.SqlConnection; AdapterType=System.Data.SqlClient.SqlDataAdapter"
///
///
/// -
/// Oracle
///
/// ConnectionString = "Data Source=tnsName; User ID=schemaUserName; Password=schemaPassword"
/// DataProviderString = "AssemblyName={Oracle.DataAccess, Version=2.112.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342}; ConnectionType=Oracle.DataAccess.Client.OracleConnection; AdapterType=Oracle.DataAccess.Client.OracleDataAdapter"
///
///
/// -
/// MySQL
///
/// ConnectionString = "Server=serverName; Database=databaseName; Uid=root; Pwd=password; allow user variables = true"
/// DataProviderString = "AssemblyName={MySql.Data, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d}; ConnectionType=MySql.Data.MySqlClient.MySqlConnection; AdapterType=MySql.Data.MySqlClient.MySqlDataAdapter"
///
///
/// -
/// SQLite
///
/// ConnectionString = "Data Source=databaseName.db; Version=3; Foreign Keys=True; FailIfMissing=True"
/// DataProviderString = "AssemblyName={System.Data.SQLite, Version=1.0.99.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139}; ConnectionType=System.Data.SQLite.SQLiteConnection; AdapterType=System.Data.SQLite.SQLiteDataAdapter"
///
///
/// -
/// SQLite (Mono native driver)
///
/// ConnectionString = "Data Source=./databaseName.db; Version=3; Foreign Keys=True; FailIfMissing=True"
/// DataProviderString = "AssemblyName={Mono.Data.Sqlite, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756}; ConnectionType=Mono.Data.Sqlite.SqliteConnection; AdapterType=Mono.Data.Sqlite.SqliteDataAdapter"
///
///
/// -
/// Access / OleDB
///
/// ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=databaseName.mdb"
/// DataProviderString = "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.OleDb.OleDbConnection; AdapterType=System.Data.OleDb.OleDbDataAdapter"
///
///
/// -
/// ODBC Connection
///
/// ConnectionString = "Driver={SQL Server Native Client 10.0}; Server=serverName; Database=databaseName; Uid=userName; Pwd=password"
/// DataProviderString = "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.Odbc.OdbcConnection; AdapterType=System.Data.Odbc.OdbcDataAdapter"
///
///
///
/// Example configuration file that defines connection settings:
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
/// ]]>
///
///
public class AdoDataConnection : IDisposable
{
#region [ Members ]
// Fields
private IDbConnection m_connection;
private DatabaseType m_databaseType;
private readonly string m_connectionString;
private readonly Type m_connectionType;
private readonly Type m_adapterType;
private readonly bool m_disposeConnection;
private bool m_disposed;
#endregion
#region [ Constructors ]
///
/// Creates and opens a new based on connection settings in configuration file.
///
/// Settings category to use for connection settings.
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
public AdoDataConnection(string settingsCategory)
{
if (string.IsNullOrWhiteSpace(settingsCategory))
throw new ArgumentNullException(nameof(settingsCategory), "Parameter cannot be null or empty");
// Only need to establish data types and load settings once per defined section since they are being loaded from config file
AdoDataConnection configuredConnection;
if (!s_configuredConnections.TryGetValue(settingsCategory, out configuredConnection))
{
string connectionString, dataProviderString;
try
{
// Load connection settings from the system settings category
ConfigurationFile config = ConfigurationFile.Current;
CategorizedSettingsElementCollection configSettings = config.Settings[settingsCategory];
connectionString = configSettings["ConnectionString"].Value;
dataProviderString = configSettings["DataProviderString"].Value;
if (string.IsNullOrWhiteSpace(connectionString))
throw new NullReferenceException("ConnectionString setting is not defined in the configuration file.");
if (string.IsNullOrWhiteSpace(dataProviderString))
throw new NullReferenceException("DataProviderString setting is not defined in the configuration file.");
}
catch (Exception ex)
{
throw new InvalidOperationException("Failed to load ADO database connection settings from configuration file: " + ex.Message, ex);
}
// Define connection settings without opening a connection
configuredConnection = new AdoDataConnection(connectionString, dataProviderString, false);
s_configuredConnections.TryAdd(settingsCategory, configuredConnection);
}
try
{
// Copy static instance data to member variables
m_databaseType = configuredConnection.m_databaseType;
m_connectionString = configuredConnection.m_connectionString;
m_connectionType = configuredConnection.m_connectionType;
m_adapterType = configuredConnection.m_adapterType;
m_disposeConnection = true;
// Open ADO.NET provider connection
m_connection = (IDbConnection)Activator.CreateInstance(m_connectionType);
m_connection.ConnectionString = m_connectionString;
m_connection.Open();
}
catch (Exception ex)
{
throw new InvalidOperationException("Failed to open ADO data connection, verify \"ConnectionString\" in configuration file: " + ex.Message, ex);
}
}
///
/// Creates and opens a new from specified and .
///
/// Database specific ADO connection string.
/// Key/value pairs that define which ADO assembly and types to load.
public AdoDataConnection(string connectionString, string dataProviderString)
: this(connectionString, dataProviderString, true)
{
}
///
/// Creates and opens a new from specified ,
/// , and .
///
/// Database specific ADO connection string.
/// The ADO type used to establish the database connection.
/// The ADO type used to load data into s.
public AdoDataConnection(string connectionString, Type connectionType, Type adapterType)
{
if (!typeof(IDbConnection).IsAssignableFrom(connectionType))
throw new ArgumentException("Connection type must implement the IDbConnection interface", nameof(connectionType));
if (!typeof(IDbDataAdapter).IsAssignableFrom(adapterType))
throw new ArgumentException("Adapter type must implement the IDbDataAdapter interface", nameof(adapterType));
m_connectionString = connectionString;
m_connectionType = connectionType;
m_adapterType = adapterType;
m_databaseType = GetDatabaseType();
m_disposeConnection = true;
try
{
// Open ADO.NET provider connection
m_connection = (IDbConnection)Activator.CreateInstance(m_connectionType);
m_connection.ConnectionString = m_connectionString;
m_connection.Open();
}
catch (Exception ex)
{
throw new InvalidOperationException("Failed to open ADO data connection, verify \"ConnectionString\": " + ex.Message, ex);
}
}
///
/// Creates a new from specified
/// and .
///
/// The database connection.
/// The ADO type used to load data into s.
/// True if the database connection should be closed when the is disposed; false otherwise.
public AdoDataConnection(IDbConnection connection, Type adapterType, bool disposeConnection)
{
if (!typeof(IDbDataAdapter).IsAssignableFrom(adapterType))
throw new ArgumentException("Adapter type must implement the IDbDataAdapter interface", nameof(adapterType));
m_connection = connection;
m_connectionString = connection.ConnectionString;
m_connectionType = connection.GetType();
m_adapterType = adapterType;
m_databaseType = GetDatabaseType();
m_disposeConnection = disposeConnection;
}
// Creates a new AdoDataConnection, optionally opening connection.
private AdoDataConnection(string connectionString, string dataProviderString, bool openConnection)
{
if (string.IsNullOrWhiteSpace(connectionString))
throw new ArgumentNullException(nameof(connectionString), "Parameter cannot be null or empty");
if (string.IsNullOrWhiteSpace(dataProviderString))
throw new ArgumentNullException(nameof(dataProviderString), "Parameter cannot be null or empty");
// Cache connection string as member level variable
m_connectionString = connectionString;
try
{
// Attempt to load configuration from an ADO.NET database connection
Dictionary settings;
string assemblyName, connectionTypeName, adapterTypeName;
Assembly assembly;
settings = dataProviderString.ParseKeyValuePairs();
assemblyName = settings["AssemblyName"].ToNonNullString();
connectionTypeName = settings["ConnectionType"].ToNonNullString();
adapterTypeName = settings["AdapterType"].ToNonNullString();
if (string.IsNullOrEmpty(connectionTypeName))
throw new NullReferenceException("ADO database connection type was undefined.");
if (string.IsNullOrEmpty(adapterTypeName))
throw new NullReferenceException("ADO database adapter type was undefined.");
assembly = Assembly.Load(new AssemblyName(assemblyName));
m_connectionType = assembly.GetType(connectionTypeName);
m_adapterType = assembly.GetType(adapterTypeName);
m_databaseType = GetDatabaseType();
m_disposeConnection = true;
}
catch (Exception ex)
{
throw new InvalidOperationException("Failed to load ADO data provider, verify \"DataProviderString\": " + ex.Message, ex);
}
if (!openConnection)
return;
try
{
// Open ADO.NET provider connection
m_connection = (IDbConnection)Activator.CreateInstance(m_connectionType);
m_connection.ConnectionString = m_connectionString;
m_connection.Open();
}
catch (Exception ex)
{
throw new InvalidOperationException("Failed to open ADO data connection, verify \"ConnectionString\": " + ex.Message, ex);
}
}
///
/// Releases the unmanaged resources before the object is reclaimed by .
///
~AdoDataConnection()
{
Dispose(false);
}
#endregion
#region [ Properties ]
///
/// Gets an open to configured ADO.NET data source.
///
public IDbConnection Connection => m_connection;
///
/// Gets the type of data adapter for configured ADO.NET data source.
///
public Type AdapterType => m_adapterType;
///
/// Gets or sets the type of the database underlying the .
///
///
/// This value is automatically assigned based on the adapter type specified in the data provider string, however,
/// if the database type cannot be determined it will be set to . In this
/// case, if you know the behavior of your custom ADO database connection matches that of another defined database
/// type, you can manually assign the database type to allow for database interaction interoperability.
///
public DatabaseType DatabaseType
{
get
{
return m_databaseType;
}
set
{
m_databaseType = value;
}
}
///
/// Gets or sets default timeout for data operations.
///
public int DefaultTimeout { get; set; } = DataExtensions.DefaultTimeoutDuration;
///
/// Gets current UTC date-time in an implementation that is proper for the connected database type.
///
public object UtcNow
{
get
{
if (IsJetEngine)
return DateTime.UtcNow.ToOADate();
if (IsSqlite)
return new DateTime(DateTime.UtcNow.Ticks, DateTimeKind.Unspecified);
return DateTime.UtcNow;
}
}
///
/// Gets the default for the connected database type.
///
public IsolationLevel DefaultIsloationLevel
{
get
{
if (IsSQLServer)
return IsolationLevel.ReadUncommitted;
return IsolationLevel.Unspecified;
}
}
///
/// Gets a value to indicate whether source database is Microsoft Access.
///
public bool IsJetEngine => m_databaseType == DatabaseType.Access;
///
/// Gets a value to indicate whether source database is Microsoft SQL Server.
///
public bool IsSQLServer => m_databaseType == DatabaseType.SQLServer;
///
/// Gets a value to indicate whether source database is MySQL.
///
public bool IsMySQL => m_databaseType == DatabaseType.MySQL;
///
/// Gets a value to indicate whether source database is Oracle.
///
public bool IsOracle => m_databaseType == DatabaseType.Oracle;
///
/// Gets a value to indicate whether source database is SQLite.
///
public bool IsSqlite => m_databaseType == DatabaseType.SQLite;
///
/// Gets a value to indicate whether source database is PostgreSQL.
///
public bool IsPostgreSQL => m_databaseType == DatabaseType.PostgreSQL;
#endregion
#region [ Methods ]
///
/// Executes the given SQL script using .
///
/// The path to the SQL script.
public void ExecuteScript(string scriptPath)
{
using (TextReader scriptReader = File.OpenText(scriptPath))
{
ExecuteScript(scriptReader);
}
}
///
/// Executes the given SQL script using .
///
/// The reader used to extract SQL statements to be executed.
public void ExecuteScript(TextReader scriptReader)
{
switch (m_databaseType)
{
case DatabaseType.SQLServer:
// For the standard way to execute a TSQL script, refer to the following.
//
// http://stackoverflow.com/questions/650098/how-to-execute-an-sql-script-file-using-c-sharp
//
// This solution was not used here because useLegacyV2RuntimeActivationPolicy
// needs to be added to the app.config file for it to work. This is not
// ideal for a core library since it has no control over an application's
// config, and it can make no assertion about the flag's suitability to the
// application. For more information, refer to the following.
//
// http://web.archive.org/web/20130128072944/http://www.marklio.com/marklio/PermaLink,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx
m_connection.ExecuteTSQLScript(scriptReader);
break;
case DatabaseType.Oracle:
m_connection.ExecuteOracleScript(scriptReader);
break;
case DatabaseType.MySQL:
Type mySqlScriptType = m_connection.GetType().Assembly.GetType("MySql.Data.MySqlClient.MySqlScript");
if ((object)mySqlScriptType != null)
{
object executor = Activator.CreateInstance(mySqlScriptType, m_connection, scriptReader.ReadToEnd());
MethodInfo executeMethod = executor.GetType().GetMethod("Execute");
executeMethod.Invoke(executor, null);
}
else
{
m_connection.ExecuteMySQLScript(scriptReader);
}
break;
default:
m_connection.ExecuteNonQuery(scriptReader.ReadToEnd());
break;
}
}
///
/// Executes the SQL statement using , and returns the number of rows affected.
///
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// The number of rows affected.
[StringFormatMethod("sqlFormat")]
public int ExecuteNonQuery(string sqlFormat, params object[] parameters)
{
return ExecuteNonQuery(DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the number of rows affected.
///
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// The number of rows affected.
[StringFormatMethod("sqlFormat")]
public int ExecuteNonQuery(int timeout, string sqlFormat, params object[] parameters)
{
string sql = GenericParameterizedQueryString(sqlFormat, parameters);
FixParameters(parameters);
return m_connection.ExecuteNonQuery(sql, timeout, parameters);
}
///
/// Executes the SQL statement using , and builds a .
///
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// A object.
[StringFormatMethod("sqlFormat")]
public IDataReader ExecuteReader(string sqlFormat, params object[] parameters)
{
return ExecuteReader(DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and builds a .
///
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// A object.
[StringFormatMethod("sqlFormat")]
public IDataReader ExecuteReader(int timeout, string sqlFormat, params object[] parameters)
{
return ExecuteReader(CommandBehavior.Default, timeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and builds a .
///
/// One of the values.
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// A object.
[StringFormatMethod("sqlFormat")]
public IDataReader ExecuteReader(CommandBehavior behavior, int timeout, string sqlFormat, params object[] parameters)
{
string sql = GenericParameterizedQueryString(sqlFormat, parameters);
FixParameters(parameters);
return m_connection.ExecuteReader(sql, behavior, timeout, parameters);
}
///
/// Executes the SQL statement using , and returns the value in the first column
/// of the first row in the result set as type .
///
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// Value in the first column of the first row in the result set.
[StringFormatMethod("sqlFormat")]
public T ExecuteScalar(string sqlFormat, params object[] parameters)
{
return ExecuteScalar(DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the value in the first column
/// of the first row in the result set as type .
///
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// Value in the first column of the first row in the result set.
[StringFormatMethod("sqlFormat")]
public T ExecuteScalar(int timeout, string sqlFormat, params object[] parameters)
{
return ExecuteScalar(default(T), timeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the value in the first column
/// of the first row in the result set as type , substituting
/// if is retrieved.
///
/// The value to be substituted if is retrieved.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// Value in the first column of the first row in the result set.
[StringFormatMethod("sqlFormat")]
public T ExecuteScalar(T defaultValue, string sqlFormat, params object[] parameters)
{
return ExecuteScalar(defaultValue, DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the value in the first column
/// of the first row in the result set as type , substituting
/// if is retrieved.
///
/// The value to be substituted if is retrieved.
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// Value in the first column of the first row in the result set.
[StringFormatMethod("sqlFormat")]
public T ExecuteScalar(T defaultValue, int timeout, string sqlFormat, params object[] parameters)
{
object value = ExecuteScalar(timeout, sqlFormat, parameters);
if ((object)value == null || value == DBNull.Value)
return defaultValue;
Type type = typeof(T);
// Nullable types cannot be used in type conversion, but we can use Nullable.GetUnderlyingType()
// to determine whether the type is nullable and convert to the underlying type instead
type = Nullable.GetUnderlyingType(type) ?? type;
// Handle Guids
if (type == typeof(Guid))
return (T)(object)System.Guid.Parse(value.ToString());
// Handle string types that may have a converter function (e.g., Enums)
if (value is string)
return value.ToString().ConvertToType(type);
// Handle native types
if (value is IConvertible)
return (T)Convert.ChangeType(value, type);
return (T)value;
}
///
/// Executes the SQL statement using , and returns the value in the first column
/// of the first row in the result set.
///
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// Value in the first column of the first row in the result set.
[StringFormatMethod("sqlFormat")]
public object ExecuteScalar(string sqlFormat, params object[] parameters)
{
return ExecuteScalar(DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the value in the first column
/// of the first row in the result set.
///
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// Value in the first column of the first row in the result set.
[StringFormatMethod("sqlFormat")]
public object ExecuteScalar(int timeout, string sqlFormat, params object[] parameters)
{
string sql = GenericParameterizedQueryString(sqlFormat, parameters);
FixParameters(parameters);
return m_connection.ExecuteScalar(sql, timeout, parameters);
}
///
/// Executes the SQL statement using , and returns the first in the result set.
///
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// The first in the result set.
[StringFormatMethod("sqlFormat")]
public DataRow RetrieveRow(string sqlFormat, params object[] parameters)
{
return RetrieveRow(DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the first in the result set.
///
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// The first in the result set.
[StringFormatMethod("sqlFormat")]
public DataRow RetrieveRow(int timeout, string sqlFormat, params object[] parameters)
{
string sql = GenericParameterizedQueryString(sqlFormat, parameters);
FixParameters(parameters);
return m_connection.RetrieveRow(m_adapterType, sql, timeout, parameters);
}
///
/// Executes the SQL statement using , and returns the first
/// of result set, if the result set contains at least one table.
///
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// A object.
[StringFormatMethod("sqlFormat")]
public DataTable RetrieveData(string sqlFormat, params object[] parameters)
{
return RetrieveData(DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the first
/// of result set, if the result set contains at least one table.
///
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// A object.
[StringFormatMethod("sqlFormat")]
public DataTable RetrieveData(int timeout, string sqlFormat, params object[] parameters)
{
string sql = GenericParameterizedQueryString(sqlFormat, parameters);
FixParameters(parameters);
return m_connection.RetrieveData(m_adapterType, sql, timeout, parameters);
}
///
/// Executes the SQL statement using , and returns the that
/// may contain multiple tables, depending on the SQL statement.
///
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// A object.
[StringFormatMethod("sqlFormat")]
public DataSet RetrieveDataSet(string sqlFormat, params object[] parameters)
{
return RetrieveDataSet(DefaultTimeout, sqlFormat, parameters);
}
///
/// Executes the SQL statement using , and returns the that
/// may contain multiple tables, depending on the SQL statement.
///
/// The time in seconds to wait for the SQL statement to execute.
/// Format string for the SQL statement to be executed.
/// The parameter values to be used to fill in parameters.
/// A object.
[StringFormatMethod("sqlFormat")]
public DataSet RetrieveDataSet(int timeout, string sqlFormat, params object[] parameters)
{
string sql = GenericParameterizedQueryString(sqlFormat, parameters);
FixParameters(parameters);
return m_connection.RetrieveDataSet(m_adapterType, sql, timeout, parameters);
}
///
/// Releases all the resources used by the object.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (!m_disposed)
{
try
{
if (disposing)
{
if (m_disposeConnection && (object)m_connection != null)
{
m_connection.Dispose();
m_connection = null;
}
}
}
finally
{
m_disposed = true; // Prevent duplicate dispose.
}
}
}
///
/// Escapes an identifier, e.g., a table or field name, using the common delimiter for the connected
/// database type or the standard ANSI escaping delimiter, i.e., double-quotes, based on the flag.
///
/// Field name to escape.
/// Force use of double-quote for identifier delimiter, per SQL-99 standard, regardless of database type.
/// Escaped identifier name.
/// value cannot be null, empty or whitespace.
public string EscapeIdentifier(string identifier, bool useAnsiQuotes = false)
{
if (string.IsNullOrWhiteSpace(identifier))
throw new ArgumentException("Value cannot be null, empty or whitespace.", nameof(identifier));
identifier = identifier.Trim();
if (useAnsiQuotes)
return $"\"{identifier}\"";
switch (m_databaseType)
{
case DatabaseType.SQLServer:
case DatabaseType.Access:
return $"[{identifier}]";
case DatabaseType.MySQL:
return $"`{identifier}`";
default:
return $"\"{identifier}\"";
}
}
///
/// Returns proper implementation for connected database type.
///
/// to format per database type.
/// Proper implementation for connected database type.
public object Bool(bool value)
{
if (IsOracle || IsPostgreSQL)
return value ? 1 : 0;
return value;
}
///
/// Returns proper implementation for connected database type.
///
/// to format per database type.
/// Proper implementation for connected database type.
public object Guid(Guid value)
{
if (IsJetEngine)
return "{" + value + "}";
if (IsSqlite || IsOracle || IsPostgreSQL)
return value.ToString().ToLower();
//return "P" + guid.ToString();
return value;
}
///
/// Retrieves from a field based on database type.
///
/// from which value needs to be retrieved.
/// Name of the field which contains .
/// .
public Guid Guid(DataRow row, string fieldName)
{
if (IsSQLServer)
return row.Field(fieldName);
return System.Guid.Parse(row.Field