/// <summary> /// Creates or updates a Settings, if a particular setting exists then updates it, else inserts it. /// Invalidates cache for the Settings when done. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="settings"></param> /// <returns></returns> public async Task <T> UpsertSettingsAsync <T>(T settings) where T : class, ISettings, new() { var settingsCreate = new List <Meta>(); var settingsUpdate = new List <Meta>(); var allSettings = await GetAllSettingsAsync(); foreach (var property in typeof(T).GetProperties()) { if (!property.CanRead || !property.CanWrite) { continue; } var value = property.GetValue(settings); var valueStr = TypeDescriptor.GetConverter(property.PropertyType).CanConvertFrom(typeof(string)) ? TypeDescriptor.GetConverter(typeof(object)).ConvertToInvariantString(value) : JsonConvert.SerializeObject(value); var key = (typeof(T).Name + "." + property.Name).ToLowerInvariant(); if (allSettings == null || !allSettings.Any(s => s.Key == key)) { settingsCreate.Add(new Meta { Key = key, Value = valueStr }); } else { var setting = await _repo.GetAsync(key); if (setting != null && setting.Value != valueStr) { setting.Value = valueStr; settingsUpdate.Add(setting); } } } if (settingsCreate.Count > 0) { await _repo.CreateRangeAsync(settingsCreate); } if (settingsUpdate.Count > 0) { await _repo.UpdateAsync(settingsUpdate); } string cacheKey = typeof(T).Name; await _cache.RemoveAsync(cacheKey); await _cache.RemoveAsync(CACHE_KEY_ALL_SETTINGS); return(settings); }