diff --git a/Disco.BI/app.config b/Disco.BI/app.config index cbdaf7eb..a13fca0a 100644 --- a/Disco.BI/app.config +++ b/Disco.BI/app.config @@ -18,4 +18,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Disco.Data/Configuration/CommunityHelpers.cs b/Disco.Data/Configuration/CommunityHelpers.cs index e34a1af5..9b20bf11 100644 --- a/Disco.Data/Configuration/CommunityHelpers.cs +++ b/Disco.Data/Configuration/CommunityHelpers.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net; -using System.Text; -using System.Threading.Tasks; namespace Disco.Data.Configuration { diff --git a/Disco.Data/Configuration/ConfigurationBase.cs b/Disco.Data/Configuration/ConfigurationBase.cs index 7618511d..a2b5ae5a 100644 --- a/Disco.Data/Configuration/ConfigurationBase.cs +++ b/Disco.Data/Configuration/ConfigurationBase.cs @@ -1,11 +1,7 @@ using Disco.Data.Repository; -using Disco.Models.Repository; -using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; -using System.Text; namespace Disco.Data.Configuration { @@ -15,29 +11,37 @@ namespace Disco.Data.Configuration public abstract string Scope { get; } + /// + /// Creates a read-write configuration instance + /// public ConfigurationBase(DiscoDataContext Database) { this.Database = Database; } - protected List Items + /// + /// Creates a read-only configuration instance + /// + public ConfigurationBase() : this(null) { } + + protected IEnumerable ItemKeys { get { - return ConfigurationCache.GetConfigurationItems(Database, this.Scope); + return ConfigurationCache.GetScopeKeys(Database, this.Scope); } } - private void SetValue(string Key, ValueType Value) + private void SetValue(string Key, T Value) { - ConfigurationCache.SetConfigurationValue(Database, this.Scope, Key, Value); + ConfigurationCache.SetValue(Database, this.Scope, Key, Value); } - private ValueType GetValue(string Key, ValueType Default) + private T GetValue(string Key, T Default) { - return ConfigurationCache.GetConfigurationValue(Database, this.Scope, Key, Default); + return ConfigurationCache.GetValue(Database, this.Scope, Key, Default); } - protected void Set(ValueType Value, [CallerMemberName] string Key = null) + protected void Set(T Value, [CallerMemberName] string Key = null) { if (Key == null) throw new ArgumentNullException("Key"); @@ -45,7 +49,7 @@ namespace Disco.Data.Configuration this.SetValue(Key, Value); } - protected ValueType Get(ValueType Default, [CallerMemberName] string Key = null) + protected T Get(T Default, [CallerMemberName] string Key = null) { if (Key == null) throw new ArgumentNullException("Key"); @@ -55,7 +59,7 @@ namespace Disco.Data.Configuration protected void SetObsfucated(string Value, [CallerMemberName] string Key = null) { - this.Set(ConfigurationCache.ObsfucateValue(Value), Key); + this.Set(Value.Obsfucate(), Key); } protected string GetDeobsfucated(string Default, [CallerMemberName] string Key = null) @@ -65,43 +69,40 @@ namespace Disco.Data.Configuration if (obsfucatedValue == null) return Default; else - return ConfigurationCache.DeobsfucateValue(obsfucatedValue); + return obsfucatedValue.Deobsfucate(); } - protected void SetAsJson(ValueType Value, [CallerMemberName] string Key = null) + protected void RemoveScope() { - if (Value == null) - this.Set(null, Key); - else - this.Set(JsonConvert.SerializeObject(Value), Key); + ConfigurationCache.RemoveScope(Database, this.Scope); } - protected ValueType GetFromJson(ValueType Default, [CallerMemberName] string Key = null) + protected void RemoveItem(string Key) { - var jsonValue = this.Get(null, Key); - - if (jsonValue == null) - return Default; - else - return JsonConvert.DeserializeObject(jsonValue); + ConfigurationCache.RemoveScopeKey(Database, this.Scope, Key); } - protected void SetAsEnum(EnumType Value, [CallerMemberName] string Key = null) + [Obsolete("Types are automatically serialized/deserialized if required, use Set(T Value) instead.")] + protected void SetAsJson(T Value, [CallerMemberName] string Key = null) { - if (Value == null) - this.Set(null, Key); - else - this.Set(Value.ToString(), Key); + this.Set(Value, Key); } - protected EnumType GetFromEnum(EnumType Default, [CallerMemberName] string Key = null) + + [Obsolete("Types are automatically serialized/deserialized if required, use Get(T Default) instead.")] + protected T GetFromJson(T Default, [CallerMemberName] string Key = null) { - var stringValue = this.Get(null, Key); - - if (stringValue == null) - return Default; - else - return (EnumType)Enum.Parse(typeof(EnumType), stringValue); + return this.Get(Default, Key); } + [Obsolete("Types are automatically serialized/deserialized if required, use Set(T Value) instead.")] + protected void SetAsEnum(T Value, [CallerMemberName] string Key = null) + { + this.Set(Value, Key); + } + [Obsolete("Types are automatically serialized/deserialized if required, use Set(T Value) instead.")] + protected T GetFromEnum(T Default, [CallerMemberName] string Key = null) + { + return this.Get(Default, Key); + } } } diff --git a/Disco.Data/Configuration/ConfigurationCache.cs b/Disco.Data/Configuration/ConfigurationCache.cs index 0810b086..ed6b0cb5 100644 --- a/Disco.Data/Configuration/ConfigurationCache.cs +++ b/Disco.Data/Configuration/ConfigurationCache.cs @@ -1,143 +1,384 @@ using Disco.Data.Repository; using Disco.Models.Repository; +using Newtonsoft.Json; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace Disco.Data.Configuration { + using ConfigurationCacheItemType = Tuple; + using ConfigurationCacheScopeType = ConcurrentDictionary>; + using ConfigurationCacheType = ConcurrentDictionary>>; + internal static class ConfigurationCache { #region Cache - private static Dictionary> configDictionary = new Dictionary>(); - private static List configurationItems = new List(); - private static object configurationItemsLock = new object(); + private static ConfigurationCacheType cacheStore = null; + private static object configChangeLock = new object(); - private static void LoadConfigurationItems(DiscoDataContext Database, string Scope, bool Reload) + private static ConfigurationCacheType Cache(DiscoDataContext Database) { - if (Reload || !configDictionary.ContainsKey(Scope)) + if (ConfigurationCache.cacheStore == null) { - lock (configurationItemsLock) + lock (configChangeLock) { - if (Reload || !configDictionary.ContainsKey(Scope)) + if (ConfigurationCache.cacheStore == null) { if (Database == null) - throw new InvalidOperationException("Cache-miss where Configuration Item requested from Cache-Only Configuration Context"); + throw new InvalidOperationException("The Configuration must be loaded at least once before a Cache-Only Configuration Context is used"); - var newItems = Database.ConfigurationItems.Where(ci => ci.Scope == Scope).ToArray(); + var configurationItems = Database.ConfigurationItems.ToArray(); - if (configDictionary.ContainsKey(Scope)) - { - var existingItems = configDictionary[Scope]; - foreach (var existingItem in existingItems.Values) - { - configurationItems.Remove(existingItem); - } - } - configurationItems.AddRange(newItems); - configDictionary[Scope] = newItems.ToDictionary(ci => ci.Key); + var indexedItems = configurationItems + .GroupBy(ci => ci.Scope) + .Select(g => + new KeyValuePair( + g.Key, + new ConfigurationCacheScopeType( + g.Select(i => new KeyValuePair(i.Key, Tuple.Create(i, (object)null)))))); + + cacheStore = new ConfigurationCacheType(indexedItems); } } } + + return ConfigurationCache.cacheStore; } - private static Dictionary> ConfigurationDictionary(DiscoDataContext Database, string IncludingScope) + + private static ConfigurationCacheItemType CacheGetItem(DiscoDataContext Database, string Scope, string Key) { - LoadConfigurationItems(Database, IncludingScope, false); - return configDictionary; - } - private static ConfigurationItem ConfigurationItem(DiscoDataContext Database, string Scope, string Key) - { - Dictionary scopeDict = default(Dictionary); - if (ConfigurationDictionary(Database, Scope).TryGetValue(Scope, out scopeDict)) + var cache = Cache(Database); + + ConfigurationCacheScopeType scopeCache; + if (cache.TryGetValue(Scope, out scopeCache)) { - ConfigurationItem item = default(ConfigurationItem); - if (scopeDict.TryGetValue(Key, out item)) + ConfigurationCacheItemType item = default(ConfigurationCacheItemType); + if (scopeCache.TryGetValue(Key, out item)) return item; } + return null; } - private static List ConfigurationItems(DiscoDataContext Database, string IncludingScope) + + private static ConfigurationCacheItemType CacheSetItem(DiscoDataContext Database, string Scope, string Key, string Value, object ObjectValue) { - LoadConfigurationItems(Database, IncludingScope, false); - return configurationItems; + if (Database == null) + throw new InvalidOperationException("Cannot save changes with a Cache-Only Configuration Context"); + + var item = CacheGetItem(Database, Scope, Key); + + if (item == null && Value == null) + { + // No Change - already null + return null; + } + else if (item == null) + { + // New Configuration Item + lock (configChangeLock) + { + // Check again for thread safety + item = CacheGetItem(Database, Scope, Key); + if (item == null) + { + // Create Configuration Item + var configItem = new ConfigurationItem() { Scope = Scope, Key = Key, Value = Value }; + item = new ConfigurationCacheItemType(configItem, ObjectValue); + + // Add Item to DB + Database.ConfigurationItems.Add(configItem); + + // Add Item to Cache + ConfigurationCacheScopeType scopeCache; + if (!cacheStore.TryGetValue(Scope, out scopeCache)) + { + scopeCache = new ConfigurationCacheScopeType(); + cacheStore.TryAdd(Scope, scopeCache); + } + scopeCache.TryAdd(Key, item); + + return item; + } + } + } + + if (item != null) + { + // Existing Configuration Item + lock (configChangeLock) + { + var configItem = item.Item1; + + // Compare Values + if (item.Item1.Value == Value) + { + // No Change - Update Cache Reference Only + return SetItemTypeValue(item, ObjectValue); + } + else + { + var entityInfo = Database.Entry(configItem); + if (entityInfo.State == System.Data.EntityState.Detached) + { + // Reload Item from DB + configItem = Database.ConfigurationItems.Where(i => i.Scope == Scope && i.Key == Key).First(); + } + + if (Value == null) + { + // Remove item from Database + Database.ConfigurationItems.Remove(configItem); + + // Remove item from Cache + ConfigurationCacheScopeType scopeCache; + if (cacheStore.TryGetValue(Scope, out scopeCache)) + { + scopeCache.TryRemove(Key, out item); + } + + return null; + } + else + { + // Update Database + configItem.Value = Value; + + // Update Cache + ConfigurationCacheScopeType scopeCache; + if (cacheStore.TryGetValue(Scope, out scopeCache)) + { + scopeCache.TryRemove(Key, out item); + item = new ConfigurationCacheItemType(configItem, ObjectValue); + scopeCache.TryAdd(Key, item); + return item; + } + } + } + } + } + + return null; + } + private static ConfigurationCacheItemType SetItemTypeValue(ConfigurationCacheItemType ExistingItem, object Value) + { + var cache = ConfigurationCache.cacheStore; + + ConfigurationCacheScopeType scopeCache; + if (cache.TryGetValue(ExistingItem.Item1.Scope, out scopeCache)) + { + ConfigurationCacheItemType newItem = new ConfigurationCacheItemType(ExistingItem.Item1, Value); + scopeCache.TryUpdate(ExistingItem.Item1.Key, newItem, ExistingItem); + return newItem; + } + + return null; } #endregion - #region Public Helpers - internal static ValueType GetConfigurationValue(DiscoDataContext Database, string Scope, string Key, ValueType Default) + #region Helpers + private static bool IsConvertableFromString(Type t) { - var ci = ConfigurationItem(Database, Scope, Key); - if (ci == null) + if (t == typeof(Boolean) || + t == typeof(Char) || + t == typeof(SByte) || + t == typeof(Byte) || + t == typeof(Int16) || t == typeof(UInt16) || + t == typeof(Int32) || t == typeof(UInt32) || + t == typeof(Int64) || t == typeof(UInt64) || + t == typeof(Single) || + t == typeof(Double) || + t == typeof(Decimal) || + t == typeof(DateTime) || + t == typeof(String)) + return true; + else + return false; + } + #endregion + + #region Cache Getters/Setters + internal static T GetValue(DiscoDataContext Database, string Scope, string Key, T Default) + { + var item = CacheGetItem(Database, Scope, Key); + + if (item == null) return Default; else - return (ValueType)Convert.ChangeType(ci.Value, typeof(ValueType)); - } - internal static void SetConfigurationValue(DiscoDataContext Database, string Scope, string Key, ValueType Value) - { - if (Database == null) - throw new InvalidOperationException("Cannot save changes with a CacheOnly Context"); - - var ci = ConfigurationItem(Database, Scope, Key); - if (ci == null && Value != null) { - lock (configurationItemsLock) + if (item.Item2 != null && item.Item2.GetType() == typeof(T)) { - ci = ConfigurationItem(Database, Scope, Key); - if (ci == null) - { - // Create Configuration Item - ci = new ConfigurationItem() { Scope = Scope, Key = Key, Value = Value.ToString() }; - // Add Item to DB & Internal Collections - Database.ConfigurationItems.Add(ci); - ConfigurationItems(Database, Scope).Add(ci); - ConfigurationDictionary(Database, Scope)[Scope].Add(Key, ci); - ci = null; - } + // Return Cached Item + return (T)item.Item2; } - } - if (ci != null) - { - lock (configurationItemsLock) + else { - var entityInfo = Database.Entry(ci); - if (entityInfo.State == System.Data.EntityState.Detached) - { - // Reload Scope from DB - LoadConfigurationItems(Database, Scope, true); - ci = ConfigurationItem(Database, Scope, Key); - } + // Convert Serialized Item + Type itemType = typeof(T); + object itemValue; - if (Value == null) + if (itemType == typeof(string)) { - Database.ConfigurationItems.Remove(ci); - configurationItems.Remove(ci); - configDictionary[Scope].Remove(Key); + // string + itemValue = item.Item1.Value; + } + else if (itemType == typeof(object)) + { + // object + itemValue = item.Item1.Value; + } + else if (IsConvertableFromString(itemType)) + { + // IConvertable + itemValue = Convert.ChangeType(item.Item1.Value, itemType); + } + else if (itemType.BaseType != null && itemType.BaseType == typeof(Enum)) + { + // Enum + itemValue = Enum.Parse(typeof(T), item.Item1.Value); } else { - ci.Value = Value.ToString(); + // JSON Deserialize + itemValue = JsonConvert.DeserializeObject(item.Item1.Value); + } + + // Set Item in Cache + SetItemTypeValue(item, itemValue); + + return (T)itemValue; + } + } + } + internal static void SetValue(DiscoDataContext Database, string Scope, string Key, T Value) + { + Type valueType = typeof(T); + string stringValue; + + if (Value == null) + { + stringValue = null; + } + else if (valueType == typeof(object)) + { + throw new ArgumentException(string.Format("Cannot serialize the configuration item [{0}].[{1}] which defines a type of [System.Object]", Scope, Key), "Value"); + } + else if (IsConvertableFromString(valueType)) + { + // string or supports IConvertable + stringValue = Value.ToString(); + } + else if (valueType.BaseType != null && valueType.BaseType == typeof(Enum)) + { + // Enum + stringValue = Value.ToString(); + } + else + { + // JSON Serialize + stringValue = JsonConvert.SerializeObject(Value); + } + + CacheSetItem(Database, Scope, Key, stringValue, Value); + } + #endregion + + #region Cache Helpers + + internal static IEnumerable GetScopeKeys(DiscoDataContext Database, string Scope) + { + var cache = Cache(Database); + + ConfigurationCacheScopeType scopeCache; + if (cache.TryGetValue(Scope, out scopeCache)) + { + return scopeCache.Keys.ToList(); + } + else + { + return Enumerable.Empty(); + } + } + + internal static void RemoveScope(DiscoDataContext Database, string Scope) + { + if (Database == null) + throw new InvalidOperationException("Cannot save changes with a Cache-Only Configuration Context"); + + lock (configChangeLock) + { + // Remove item from Database + var items = Database.ConfigurationItems.Where(i => i.Scope == Scope).ToList(); + items.ForEach(i => Database.ConfigurationItems.Remove(i)); + + // Remove item from Cache + if (cacheStore != null) + { + ConfigurationCacheScopeType scopeCache; + cacheStore.TryRemove(Scope, out scopeCache); + } + } + } + + internal static void RemoveScopeKey(DiscoDataContext Database, string Scope, string Key) + { + if (Database == null) + throw new InvalidOperationException("Cannot save changes with a Cache-Only Configuration Context"); + + lock (configChangeLock) + { + var cacheItem = CacheGetItem(Database, Scope, Key); + ConfigurationItem configItem = null; + + // Remove item from Database + if (cacheItem != null) + { + configItem = cacheItem.Item1; + + var entityInfo = Database.Entry(configItem); + if (entityInfo.State == System.Data.EntityState.Detached) + { + // Reload Item from DB + configItem = Database.ConfigurationItems.Where(i => i.Scope == Scope && i.Key == Key).FirstOrDefault(); + } + } + if (configItem == null) + { + // Load Item from DB + configItem = Database.ConfigurationItems.Where(i => i.Scope == Scope && i.Key == Key).FirstOrDefault(); + } + if (configItem != null) + { + Database.ConfigurationItems.Remove(configItem); + } + + // Remove item from Cache + if (cacheItem != null) + { + ConfigurationCacheScopeType scopeCache; + if (cacheStore.TryGetValue(Scope, out scopeCache)) + { + scopeCache.TryRemove(Key, out cacheItem); } } } } - internal static List GetConfigurationItems(DiscoDataContext Database, string Scope) - { - return ConfigurationDictionary(Database, Scope)[Scope].Values.ToList(); - } + #endregion - internal static string ObsfucateValue(string Value) + #region Obsfucation Helpers + internal static string Obsfucate(this string Value) { if (string.IsNullOrEmpty(Value)) return Value; else return Convert.ToBase64String(Encoding.Unicode.GetBytes(Value)); } - internal static string DeobsfucateValue(string ObsfucatedValue) + internal static string Deobsfucate(this string ObsfucatedValue) { if (string.IsNullOrEmpty(ObsfucatedValue)) return ObsfucatedValue; @@ -145,6 +386,5 @@ namespace Disco.Data.Configuration return Encoding.Unicode.GetString(Convert.FromBase64String(ObsfucatedValue)); } #endregion - } } diff --git a/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs b/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs index 43299481..b50caa2f 100644 --- a/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs +++ b/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs @@ -1,9 +1,5 @@ using Disco.Data.Repository; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Data.Configuration.Modules { @@ -20,18 +16,18 @@ namespace Disco.Data.Configuration.Modules { get { - return GetFromJson>>(null); + return Get>>(null); } set { - SetAsJson(value); + Set(value); } } public bool? SearchAllForestServers { - get { return GetFromJson(null); } - set { SetAsJson(value); } + get { return Get(null); } + set { Set(value); } } } } diff --git a/Disco.Data/Configuration/Modules/BootstrapperConfiguration.cs b/Disco.Data/Configuration/Modules/BootstrapperConfiguration.cs index c9f754bd..a74522fd 100644 --- a/Disco.Data/Configuration/Modules/BootstrapperConfiguration.cs +++ b/Disco.Data/Configuration/Modules/BootstrapperConfiguration.cs @@ -1,8 +1,4 @@ using Disco.Data.Repository; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Disco.Data.Configuration.Modules { diff --git a/Disco.Data/Configuration/Modules/DeviceProfileConfiguration.cs b/Disco.Data/Configuration/Modules/DeviceProfileConfiguration.cs deleted file mode 100644 index d7418014..00000000 --- a/Disco.Data/Configuration/Modules/DeviceProfileConfiguration.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3. -// -// -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using Disco.Models.Repository; - -//namespace Disco.Data.Configuration.Modules -//{ -// public class DeviceProfileConfiguration : ConfigurationBase -// { -// private DeviceProfilesConfiguration deviceProfilesConfig; -// private DeviceProfile deviceProfile; - -// public DeviceProfileConfiguration(ConfigurationContext Context, DeviceProfile DeviceProfile) -// : base(Context) -// { -// this.deviceProfilesConfig = Context.DeviceProfiles; -// this.deviceProfile = DeviceProfile; -// } - -// public override string Scope -// { -// get -// { -// return string.Format("DeviceProfile:{0}", this.deviceProfile.Id); -// } -// } - -// public string ComputerNameTemplate -// { -// get -// { -// return this.GetValue("ComputerNameTemplate", "DeviceProfile.ShortName + '-' + SerialNumber"); -// } -// set -// { -// this.SetValue("ComputerNameTemplate", value); -// } -// } - -// public enum DeviceProfileDistributionTypes : int -// { -// OneToMany = 0, -// OneToOne = 1 -// } -// public DeviceProfileDistributionTypes DistributionType -// { -// get -// { -// return (DeviceProfileDistributionTypes)this.GetValue("DistributionType", (int)DeviceProfileDistributionTypes.OneToMany); -// } -// set -// { -// this.SetValue("DistributionType", (int)value); -// } -// } -// public string OrganisationalUnit -// { -// get -// { -// return this.GetValue("OrganisationalUnit", null); -// } -// set -// { -// this.SetValue("OrganisationalUnit", value); -// } -// } -// public bool AllocateWirelessCertificate -// { -// get -// { -// return this.GetValue("AllocateWirelessCertificate", false); -// } -// set -// { -// this.SetValue("AllocateWirelessCertificate", value); -// } -// } - - - -// } -//} diff --git a/Disco.Data/Configuration/Modules/DeviceProfilesConfiguration.cs b/Disco.Data/Configuration/Modules/DeviceProfilesConfiguration.cs index f54f079e..717f433c 100644 --- a/Disco.Data/Configuration/Modules/DeviceProfilesConfiguration.cs +++ b/Disco.Data/Configuration/Modules/DeviceProfilesConfiguration.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Disco.Models.Repository; -using Disco.Data.Repository; +using Disco.Data.Repository; +using System; namespace Disco.Data.Configuration.Modules { diff --git a/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs b/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs index e2e19e76..04d6786e 100644 --- a/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs +++ b/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs @@ -1,10 +1,7 @@ using Disco.Data.Repository; +using Disco.Models.BI.Job; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Disco.Models.BI.Job; namespace Disco.Data.Configuration.Modules { @@ -46,14 +43,14 @@ namespace Disco.Data.Configuration.Modules public LocationModes LocationMode { - get { return GetFromEnum(LocationModes.Unrestricted); } - set { SetAsEnum(value); } + get { return Get(LocationModes.Unrestricted); } + set { Set(value); } } public List LocationList { - get { return GetFromJson>(new List()); } - set { SetAsJson(value); } + get { return Get>(new List()); } + set { Set(value); } } } } diff --git a/Disco.Data/Configuration/Modules/OrganisationAddressesConfiguration.cs b/Disco.Data/Configuration/Modules/OrganisationAddressesConfiguration.cs index e15a0275..19045ffe 100644 --- a/Disco.Data/Configuration/Modules/OrganisationAddressesConfiguration.cs +++ b/Disco.Data/Configuration/Modules/OrganisationAddressesConfiguration.cs @@ -1,38 +1,22 @@ -using System; +using Disco.Data.Repository; +using Disco.Models.BI.Config; +using Newtonsoft.Json; using System.Collections.Generic; using System.Linq; -using System.Text; -using Disco.Models.BI.Config; -using Disco.Models.Repository; -using Newtonsoft.Json; -using Disco.Data.Repository; namespace Disco.Data.Configuration.Modules { public class OrganisationAddressesConfiguration : ConfigurationBase { + private const string scope = "OrganisationAddresses"; + public OrganisationAddressesConfiguration(DiscoDataContext Database) : base(Database) { } - public override string Scope { get { return "OrganisationAddresses"; } } + public override string Scope { get { return scope; } } public OrganisationAddress GetAddress(int Id) { - var address = default(OrganisationAddress); - var addressString = this.Get(null, Id.ToString()); - if (addressString != null) - { - if (addressString.StartsWith("{")) - { - // Assume Json - address = JsonConvert.DeserializeObject(addressString); - } - else - { - // Assume Old Storage Method - address = OrganisationAddress.FromConfigurationEntry(Id, addressString); - } - } - return address; + return this.Get(null, Id.ToString()); } public OrganisationAddress SetAddress(OrganisationAddress Address) { @@ -41,25 +25,21 @@ namespace Disco.Data.Configuration.Modules Address.Id = NextOrganisationAddressId; } - string addressString = JsonConvert.SerializeObject(Address); + this.Set(Address, Address.Id.ToString()); - this.Set(addressString, Address.Id.ToString()); //Address.ToConfigurationEntry()); return Address; } public void RemoveAddress(int Id) { - // Set Config Item to null = Remove Configuration Item - this.Set(null, Id.ToString()); + // Remove Configuration Item + this.RemoveItem(Id.ToString()); } public List Addresses { get { - return this.Items.Select(ca => ca.Value.StartsWith("{") ? - JsonConvert.DeserializeObject(ca.Value) : - OrganisationAddress.FromConfigurationEntry(int.Parse(ca.Key), ca.Value) - ).ToList(); + return this.ItemKeys.Select(key => this.Get(null, key)).ToList(); } } @@ -78,5 +58,19 @@ namespace Disco.Data.Configuration.Modules } } + internal static void MigrateDatabase(DiscoDataContext Database) + { + // Migrate all organisation addresses to JSON + if (Database.ConfigurationItems.Count(i => i.Scope == scope && !i.Value.StartsWith("{")) > 0) + { + var items = Database.ConfigurationItems.Where(i => i.Scope == scope && !i.Value.StartsWith("{")).ToList(); + items.ForEach(i => + { + i.Value = JsonConvert.SerializeObject(OrganisationAddress.FromConfigurationEntry(int.Parse(i.Key), i.Value)); + }); + Database.SaveChanges(); + } + } + } } diff --git a/Disco.Data/Configuration/SystemConfiguration.cs b/Disco.Data/Configuration/SystemConfiguration.cs index 8a327d64..cbf41575 100644 --- a/Disco.Data/Configuration/SystemConfiguration.cs +++ b/Disco.Data/Configuration/SystemConfiguration.cs @@ -1,13 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Disco.Data.Repository; -using Disco.Models.Repository; -using System.IO; -using System.Security.Cryptography; +using Disco.Data.Repository; using Disco.Models.BI.Interop.Community; -using Newtonsoft.Json; +using System; +using System.IO; namespace Disco.Data.Configuration { @@ -270,11 +264,11 @@ namespace Disco.Data.Configuration { get { - return this.GetFromJson(null); + return this.Get(null); } set { - this.SetAsJson(value); + this.Set(value); } } public bool UpdateBetaDeployment diff --git a/Disco.Data/Disco.Data.csproj b/Disco.Data/Disco.Data.csproj index be4d4ada..f23b4c1b 100644 --- a/Disco.Data/Disco.Data.csproj +++ b/Disco.Data/Disco.Data.csproj @@ -77,7 +77,6 @@ - @@ -203,7 +202,7 @@ - + diff --git a/Disco.Data/Repository/DiscoDataSeeder.cs b/Disco.Data/Repository/DiscoDataSeeder.cs index 4c71ced0..8a954649 100644 --- a/Disco.Data/Repository/DiscoDataSeeder.cs +++ b/Disco.Data/Repository/DiscoDataSeeder.cs @@ -19,7 +19,11 @@ namespace Disco.Data.Repository Database.SeedJobTypes(); Database.SeedJobSubTypes(); + Database.SaveChanges(); + // Migration Maintenance + Database.MigrateConfiguration(); + Database.MigratePreDomainObjects(); } @@ -311,6 +315,14 @@ namespace Disco.Data.Repository } // End Added: 2013-02-07 G# + public static void MigrateConfiguration(this DiscoDataContext Database) + { + // Organisation Addresses - Force all to JSON serializing + Configuration.Modules.OrganisationAddressesConfiguration.MigrateDatabase(Database); + + Database.SaveChanges(); + } + #region Migrate Users SQL private const string MigratePreDomainUsers_Sql = @"INSERT INTO [Users] SELECT @IdNew, u.DisplayName, u.Surname, u.GivenName, u.PhoneNumber, u.EmailAddress FROM [Users] u WHERE [Id]=@IdExisting; diff --git a/Disco.Services/App.config b/Disco.Services/App.config index 5ced0be2..c9457dd5 100644 --- a/Disco.Services/App.config +++ b/Disco.Services/App.config @@ -14,4 +14,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Disco.Web.Extensions/App.config b/Disco.Web.Extensions/App.config index 5ced0be2..c9457dd5 100644 --- a/Disco.Web.Extensions/App.config +++ b/Disco.Web.Extensions/App.config @@ -14,4 +14,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs b/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs index 4cdc329f..6eec7f7d 100644 --- a/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs +++ b/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs @@ -31,7 +31,7 @@ namespace Disco.Web.Areas.Config.Controllers if (m == null || m.DeviceProfile == null) throw new ArgumentException("Invalid Device Profile Id", "id"); - m.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses; + m.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses.OrderBy(a => a.Name).ToList(); if (m.DeviceProfile.DefaultOrganisationAddress.HasValue) m.DefaultOrganisationAddress = Database.DiscoConfiguration.OrganisationAddresses.GetAddress(m.DeviceProfile.DefaultOrganisationAddress.Value); diff --git a/Disco.Web/Areas/Config/Controllers/OrganisationController.cs b/Disco.Web/Areas/Config/Controllers/OrganisationController.cs index e109ce47..4467c432 100644 --- a/Disco.Web/Areas/Config/Controllers/OrganisationController.cs +++ b/Disco.Web/Areas/Config/Controllers/OrganisationController.cs @@ -2,6 +2,7 @@ using Disco.Services.Authorization; using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Web; +using System.Linq; using System.Web.Mvc; namespace Disco.Web.Areas.Config.Controllers @@ -18,7 +19,7 @@ namespace Disco.Web.Areas.Config.Controllers viewModel.OrganisationName = Database.DiscoConfiguration.OrganisationName; viewModel.MultiSiteMode = Database.DiscoConfiguration.MultiSiteMode; - viewModel.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses; + viewModel.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses.OrderBy(a => a.Name).ToList(); // UI Extensions UIExtensions.ExecuteExtensions(this.ControllerContext, viewModel); diff --git a/Disco.Web/Disco.Web.csproj b/Disco.Web/Disco.Web.csproj index fa19569b..9821bdba 100644 --- a/Disco.Web/Disco.Web.csproj +++ b/Disco.Web/Disco.Web.csproj @@ -2053,7 +2053,7 @@ False - + diff --git a/Disco.Web/Models/Job/LogWarrantyModel.cs b/Disco.Web/Models/Job/LogWarrantyModel.cs index 6501bad8..ef9546f9 100644 --- a/Disco.Web/Models/Job/LogWarrantyModel.cs +++ b/Disco.Web/Models/Job/LogWarrantyModel.cs @@ -96,7 +96,7 @@ namespace Disco.Web.Models.Job if (!string.IsNullOrEmpty(WarrantyProviderId)) WarrantyProvider = Plugins.GetPluginFeature(WarrantyProviderId, typeof(WarrantyProviderFeature)); - this.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses; + this.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses.OrderBy(a => a.Name).ToList(); if (!IsPostBack && !this.OrganisationAddressId.HasValue) {