From 3d068d174cd46d39c66f7687a966a816d4fdf5fb Mon Sep 17 00:00:00 2001 From: Sergii Lutai Date: Fri, 25 Nov 2016 13:01:43 +0200 Subject: [PATCH] Added possibility for optional table name configuration within azure table storage. Optional parameter "ApplicationName" can be added as attribute of item or as parameter of connectionString attribute. Optional parameter "TableName" can be added as attribute of item or as parameter of connectionString attribute. --- .../AzureTableStorageErrorLog.cs | 88 +++++++++++++++---- 1 file changed, 73 insertions(+), 15 deletions(-) diff --git a/src/Elmah.AzureTableStorage/AzureTableStorageErrorLog.cs b/src/Elmah.AzureTableStorage/AzureTableStorageErrorLog.cs index 4ba5e9c..a3d8d1b 100644 --- a/src/Elmah.AzureTableStorage/AzureTableStorageErrorLog.cs +++ b/src/Elmah.AzureTableStorage/AzureTableStorageErrorLog.cs @@ -14,10 +14,13 @@ namespace Elmah.AzureTableStorage public class AzureTableStorageErrorLog : ErrorLog { private readonly CloudTable _cloudTable; - private const string TableName = "Elmah"; + + private static volatile string TableName = "Elmah"; private const int MaxAppNameLength = 60; + private const int MaxTableNameLength = 60; + /// /// Initializes a new instance of the class /// using a dictionary of configured settings. @@ -28,27 +31,45 @@ public AzureTableStorageErrorLog(IDictionary config) if (config == null) throw new ArgumentNullException("config"); - var connectionString = ElmahHelper.GetConnectionString(config); + #region Read properties of ErrorLog config item // - // If there is no connection string to use then throw an - // exception to abort construction. + // Set the application name as this implementation provides + // per-application isolation over a single store. // - if (connectionString.Length == 0) - throw new ApplicationException("Connection string is missing for the Azure Table Storage error log."); - - var cloudStorageAccount = CloudStorageAccount.Parse(connectionString); - var tableClient = cloudStorageAccount.CreateCloudTableClient(); - _cloudTable = tableClient.GetTableReference(TableName); - _cloudTable.CreateIfNotExists(); + var appName = config.Find("applicationName", string.Empty); // - // Set the application name as this implementation provides - // per-application isolation over a single store. + // Set the table name. This implementation provides + // table-per-application-config isolation over a single store. // - var appName = config.Find("applicationName", string.Empty); + var tableName = config.Find("tableName", string.Empty); + + #endregion Read properties of ErrorLog config item + + #region Read properties of ErrorLog connection string + + var cfgBuilder = new System.Data.Common.DbConnectionStringBuilder(); + var originalConnectionString = ElmahHelper.GetConnectionString(config); + cfgBuilder.ConnectionString = originalConnectionString; + + // Try to override ApplicationName from connection string + if (cfgBuilder.ContainsKey("ApplicationName")) + { + appName = (string)cfgBuilder["ApplicationName"]; + cfgBuilder.Remove("ApplicationName"); + } + + // Try to override TableName from connection string + if (cfgBuilder.ContainsKey("TableName")) + { + tableName = (string)cfgBuilder["TableName"]; + cfgBuilder.Remove("TableName"); + } + + #endregion Read properties of ErrorLog connection string if (appName.Length > MaxAppNameLength) { @@ -57,7 +78,44 @@ public AzureTableStorageErrorLog(IDictionary config) MaxAppNameLength.ToString("N0"))); } - ApplicationName = appName; + if (tableName.Length > MaxTableNameLength) + { + throw new ApplicationException(string.Format( + "Table name is too long. Maximum length allowed is {0} characters.", + MaxTableNameLength.ToString("N0"))); + } + + if (!string.IsNullOrWhiteSpace(appName)) + { + ApplicationName = appName; + } + + if (!string.IsNullOrWhiteSpace(tableName)) + { + TableName = tableName; + } + + var newConnectionString = string.Join(";", originalConnectionString.Split(';').Where(item => !item.StartsWith("ApplicationName=", StringComparison.OrdinalIgnoreCase) && !item.StartsWith("TableName=", StringComparison.OrdinalIgnoreCase))); + var newConnectionStringBuilder = new System.Data.Common.DbConnectionStringBuilder(); + newConnectionStringBuilder.ConnectionString = newConnectionString; + + if (!cfgBuilder.EquivalentTo(newConnectionStringBuilder)) + { + throw new ApplicationException("Connection string contains invalid parameters."); + } + + // + // If there is no connection string to use then throw an + // exception to abort construction. + // + + if (cfgBuilder.ConnectionString.Length == 0) + throw new ApplicationException("Connection string is missing for the Azure Table Storage error log."); + + var cloudStorageAccount = CloudStorageAccount.Parse(newConnectionString); + var tableClient = cloudStorageAccount.CreateCloudTableClient(); + _cloudTable = tableClient.GetTableReference(TableName); + _cloudTable.CreateIfNotExists(); } ///