diff --git a/ProcessorLibrary/Configuration.cs b/ProcessorLibrary/Configuration.cs new file mode 100644 index 0000000..368b60a --- /dev/null +++ b/ProcessorLibrary/Configuration.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Concurrent; +using System.Configuration; + +namespace ProcessorLibrary +{ + public static class Configuration + { + private static readonly string DefaultProviderKey = "DefaultProvider"; + private static readonly string DefaultProvider = GetAppSetting(DefaultProviderKey); + private static readonly ConcurrentDictionary ConnectionSettings = new ConcurrentDictionary(); + + public static ConnectionStringSettings LoadConnectionSettings(string connectionKey) + { + if (string.IsNullOrEmpty(connectionKey)) + throw new ArgumentNullException(nameof(connectionKey)); + + ConnectionStringSettings settings; + if (!ConnectionSettings.TryGetValue(connectionKey, out settings)) + { + string connectionName = GetAppSetting(connectionKey, true); + if (!string.IsNullOrEmpty(connectionName)) + { + // A named appSetting was found, use the value as the connection name + settings = GetConnectionSettings(connectionName); + } + else + { + // Use the connectionKey key as the connection name + settings = GetConnectionSettings(connectionKey); + } + + ConnectionSettings[connectionKey] = settings; + } + + return settings; + } + + public static ConnectionStringSettings GetConnectionSettings(string connectionName) + { + ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[connectionName]; + if (settings == null) + throw new SettingsPropertyNotFoundException($"{connectionName} connection not found."); + + if (string.IsNullOrEmpty(settings.ConnectionString)) + throw new ArgumentNullException($"{connectionName} connectionString value is blank."); + + // When no provider is specified in the ConnectionString use the default + if (string.IsNullOrEmpty(settings.ProviderName)) + { + settings.ProviderName = DefaultProvider; + } + + return settings; + } + + public static string GetAppSetting(string settingKey, bool allowNulls = false) + { + string settingValue = ConfigurationManager.AppSettings[settingKey]; + if (!allowNulls && settingValue == null) + throw new SettingsPropertyNotFoundException($"{settingKey} appSetting not found."); + + return settingValue; + } + } +} diff --git a/ProcessorLibrary/DataAccess.cs b/ProcessorLibrary/DataAccess.cs index a8289b0..eb483b5 100644 --- a/ProcessorLibrary/DataAccess.cs +++ b/ProcessorLibrary/DataAccess.cs @@ -1,44 +1,87 @@ using Dapper; using System; -using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Configuration; using System.Data; -using System.Data.SqlClient; -using System.Linq; -using System.Text; +using System.Data.Common; using System.Threading.Tasks; namespace ProcessorLibrary { public static class DataAccess { - private static string LoadConnectionString(string id = "FitIndex") + private static readonly string LogDatabase = "LoggingDb"; + private static readonly ConcurrentDictionary ProviderFactories = new ConcurrentDictionary(); + + public static int InsertDeploymentAction(string deploymentType, string siteName) { - return System.Configuration.ConfigurationManager.ConnectionStrings[id].ConnectionString; + var param = new + { + DeploymentType = deploymentType, + LoggedInUser = string.Empty, + SiteName = siteName + }; + + return RunProcedure(LogDatabase, "dbo.spDeploymentLog_InsertAction", param); } - public static void InsertOutOfCycleFileChange(string fileName, string changeType) + public static int InsertOutOfCycleFileChange(string fileName, string changeType) { - using (IDbConnection cnn = new SqlConnection(LoadConnectionString("LoggingDb"))) + var param = new { - var p = new DynamicParameters(); - p.Add("@FileChanged", fileName); - p.Add("@ChangeType", changeType); + FileChange = fileName, + ChangeType = changeType + }; - cnn.Execute("dbo.spOutOfCycleFileChanges_Insert", p, commandType: CommandType.StoredProcedure); + return RunProcedure(LogDatabase, "dbo.spOutOfCycleFileChanges_Insert", param); + } + + private static int RunProcedure(string connectionKey, string procedureName, object param = null) + { + using (IDbConnection connection = GetConnection(connectionKey)) + { + return connection.Execute(procedureName, param, commandTimeout: connection.ConnectionTimeout, commandType: CommandType.StoredProcedure); } } - public static void InsertDeploymentAction(string deploymentType, string siteName) + private static Task RunProcedureAsync(string connectionKey, string procedureName, object param = null) { - using (IDbConnection cnn = new SqlConnection(LoadConnectionString("LoggingDb"))) + using (IDbConnection connection = GetConnection(connectionKey)) { - var p = new DynamicParameters(); - p.Add("@DeploymentType", deploymentType); - p.Add("@LoggedInUser", ""); - p.Add("@SiteName", siteName); + return connection.ExecuteAsync(procedureName, param, commandTimeout: connection.ConnectionTimeout, commandType: CommandType.StoredProcedure); + } + } + + private static IDbConnection GetConnection(string connectionName) + { + ConnectionStringSettings settings = Configuration.GetConnectionSettings(connectionName); + DbProviderFactory factory = GetProviderFactory(settings.ProviderName); - cnn.Execute("dbo.spDeploymentLog_InsertAction", p, commandType: CommandType.StoredProcedure); + try + { + IDbConnection connection = factory.CreateConnection(); + connection.ConnectionString = settings.ConnectionString; + return connection; + } + catch (Exception ex) + { + throw new Exception($"{factory.GetType().Name} failed to create a connection.", ex); + } + } + + private static DbProviderFactory GetProviderFactory(string providerName = "System.Data.SqlClient") + { + DbProviderFactory providerFactory; + if (!ProviderFactories.TryGetValue(providerName, out providerFactory)) + { + providerFactory = DbProviderFactories.GetFactory(providerName); + if (providerFactory == null) + throw new NotSupportedException($"{providerName} database provider is not available."); + + ProviderFactories[providerName] = providerFactory; } + + return providerFactory; } } }