From 71c0240437af0e7a08e6a6b5e8cc4f68b3130587 Mon Sep 17 00:00:00 2001 From: Mikhail Shabanov Date: Sun, 31 May 2020 15:43:39 +0200 Subject: [PATCH] Mongo db saving --- .../AchievementSectionDictionary.cs | 3 +- .../Dictionaries/ClanRoleDictionary.cs | 3 +- .../Dictionaries/LocalizableString.cs | 20 ++++++ .../Dictionaries/NationDictionary.cs | 3 +- .../Dictionaries/VehicleTypeDictionary.cs | 3 +- .../IMongoSettings.cs | 18 +++++ .../DictionariesDataAccessor.cs | 66 +++++++++++++++++++ .../IDictionariesDataAccessor.cs | 19 ++++++ .../WotBlitzStatisticsDataAccessInstaller.cs | 13 ++++ .../WotBlitzStatisticsPro.DataAccess.csproj | 16 +++++ .../MongoSettings.cs | 10 +++ WotBlitzStatisticsPro.GraphQl/Startup.cs | 4 ++ .../appsettings.json | 6 +- .../Dictionaries/StaticDictionariesUpdater.cs | 37 ++++++++--- .../WargamingDictionaries.cs | 5 +- .../WotBlitzStatisticsLogicInstaller.cs | 5 +- .../WotBlitzStatisticsPro.Logic.csproj | 1 + WotBlitzStatisticsPro.sln | 7 ++ 18 files changed, 217 insertions(+), 22 deletions(-) create mode 100644 WotBlitzStatisticsPro.Common/Dictionaries/LocalizableString.cs create mode 100644 WotBlitzStatisticsPro.Common/IMongoSettings.cs create mode 100644 WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs create mode 100644 WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs create mode 100644 WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsDataAccessInstaller.cs create mode 100644 WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsPro.DataAccess.csproj create mode 100644 WotBlitzStatisticsPro.GraphQl/MongoSettings.cs diff --git a/WotBlitzStatisticsPro.Common/Dictionaries/AchievementSectionDictionary.cs b/WotBlitzStatisticsPro.Common/Dictionaries/AchievementSectionDictionary.cs index 0d6d7d1..dfd1ad0 100644 --- a/WotBlitzStatisticsPro.Common/Dictionaries/AchievementSectionDictionary.cs +++ b/WotBlitzStatisticsPro.Common/Dictionaries/AchievementSectionDictionary.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using WotBlitzStatisticsPro.Common.Model; namespace WotBlitzStatisticsPro.Common.Dictionaries { @@ -21,7 +20,7 @@ namespace WotBlitzStatisticsPro.Common.Dictionaries /// /// Localized section names /// - public Dictionary AchievementSectionNames { get; set; } + public List AchievementSectionNames { get; set; } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Common/Dictionaries/ClanRoleDictionary.cs b/WotBlitzStatisticsPro.Common/Dictionaries/ClanRoleDictionary.cs index 1ad9544..2bf9180 100644 --- a/WotBlitzStatisticsPro.Common/Dictionaries/ClanRoleDictionary.cs +++ b/WotBlitzStatisticsPro.Common/Dictionaries/ClanRoleDictionary.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using WotBlitzStatisticsPro.Common.Model; namespace WotBlitzStatisticsPro.Common.Dictionaries { @@ -16,6 +15,6 @@ namespace WotBlitzStatisticsPro.Common.Dictionaries /// /// Localized clan role names /// - public Dictionary ClanRoleNames { get; set; } + public List ClanRoleNames { get; set; } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Common/Dictionaries/LocalizableString.cs b/WotBlitzStatisticsPro.Common/Dictionaries/LocalizableString.cs new file mode 100644 index 0000000..74044e4 --- /dev/null +++ b/WotBlitzStatisticsPro.Common/Dictionaries/LocalizableString.cs @@ -0,0 +1,20 @@ +using WotBlitzStatisticsPro.Common.Model; + +namespace WotBlitzStatisticsPro.Common.Dictionaries +{ + /// + /// Represents localizable string + /// + public class LocalizableString + { + /// + /// Language. + /// + public RequestLanguage Language { get; set; } + + /// + /// Localizable string. + /// + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Common/Dictionaries/NationDictionary.cs b/WotBlitzStatisticsPro.Common/Dictionaries/NationDictionary.cs index 8908779..20ef147 100644 --- a/WotBlitzStatisticsPro.Common/Dictionaries/NationDictionary.cs +++ b/WotBlitzStatisticsPro.Common/Dictionaries/NationDictionary.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using WotBlitzStatisticsPro.Common.Model; namespace WotBlitzStatisticsPro.Common.Dictionaries { @@ -16,6 +15,6 @@ namespace WotBlitzStatisticsPro.Common.Dictionaries /// /// Nation /// - public Dictionary NationNames { get; set; } + public List NationNames { get; set; } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Common/Dictionaries/VehicleTypeDictionary.cs b/WotBlitzStatisticsPro.Common/Dictionaries/VehicleTypeDictionary.cs index e755e57..71982be 100644 --- a/WotBlitzStatisticsPro.Common/Dictionaries/VehicleTypeDictionary.cs +++ b/WotBlitzStatisticsPro.Common/Dictionaries/VehicleTypeDictionary.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using WotBlitzStatisticsPro.Common.Model; namespace WotBlitzStatisticsPro.Common.Dictionaries { @@ -16,7 +15,7 @@ namespace WotBlitzStatisticsPro.Common.Dictionaries /// /// Vehicle type localized name /// - public Dictionary VehicleTypeNames { get; set; } + public List VehicleTypeNames { get; set; } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Common/IMongoSettings.cs b/WotBlitzStatisticsPro.Common/IMongoSettings.cs new file mode 100644 index 0000000..8d29203 --- /dev/null +++ b/WotBlitzStatisticsPro.Common/IMongoSettings.cs @@ -0,0 +1,18 @@ +namespace WotBlitzStatisticsPro.Common +{ + /// + /// MongoDB connection settings + /// + public interface IMongoSettings + { + /// + /// Connection string + /// + string ConnectionString { get; set; } + + /// + /// Database name + /// + string DatabaseName { get; set; } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs b/WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs new file mode 100644 index 0000000..4cd4a64 --- /dev/null +++ b/WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using MongoDB.Driver; +using WotBlitzStatisticsPro.Common; +using WotBlitzStatisticsPro.Common.Dictionaries; + +namespace WotBlitzStatisticsPro.DataAccess +{ + public class DictionariesDataAccessor : IDictionariesDataAccessor + { + private const string LanguagesCollectionName = "dictionary-languages"; + private const string NationsCollectionName = "dictionary-natons"; + private const string VehicleTypesCollectionName = "dictionary-vehicle-types"; + private const string ClanRolesCollectionName = "dictionary-clan-roles"; + private const string AchievementsSectionsCollectionName = "dictionary-achievements-sections"; + + private readonly IMongoDatabase _database; + + public DictionariesDataAccessor(IMongoSettings settings) + { + var client = new MongoClient(settings.ConnectionString); + _database = client.GetDatabase(settings.DatabaseName); + } + + public async Task UpdateLanguages(List languages) + { + var dbLanguages = _database.GetCollection(LanguagesCollectionName); + + await dbLanguages.DeleteManyAsync(Builders.Filter.Empty); + await dbLanguages.InsertManyAsync(languages); + } + + public async Task UpdateNations(List nations) + { + var dbNations = _database.GetCollection(NationsCollectionName); + + await dbNations.DeleteManyAsync(Builders.Filter.Empty); + await dbNations.InsertManyAsync(nations); + } + + public async Task UpdateVehicleTypes(List vehicleTypes) + { + var dbVehicleTypes = _database.GetCollection(VehicleTypesCollectionName); + + await dbVehicleTypes.DeleteManyAsync(Builders.Filter.Empty); + await dbVehicleTypes.InsertManyAsync(vehicleTypes); + } + + public async Task UpdateClanRoles(List clanRoles) + { + var dbClanRoles = _database.GetCollection(ClanRolesCollectionName); + + await dbClanRoles.DeleteManyAsync(Builders.Filter.Empty); + await dbClanRoles.InsertManyAsync(clanRoles); + } + + public async Task UpdateAchievementsSections(List achievementSections) + { + var dbAchievementSections = + _database.GetCollection(AchievementsSectionsCollectionName); + + await dbAchievementSections.DeleteManyAsync(Builders.Filter.Empty); + await dbAchievementSections.InsertManyAsync(achievementSections); + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs b/WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs new file mode 100644 index 0000000..85d9796 --- /dev/null +++ b/WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using WotBlitzStatisticsPro.Common.Dictionaries; + +namespace WotBlitzStatisticsPro.DataAccess +{ + public interface IDictionariesDataAccessor + { + Task UpdateLanguages(List languages); + + Task UpdateNations(List nations); + + Task UpdateVehicleTypes(List vehicleTypes); + + Task UpdateClanRoles(List clanRoles); + + Task UpdateAchievementsSections(List achievementSections); + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsDataAccessInstaller.cs b/WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsDataAccessInstaller.cs new file mode 100644 index 0000000..e7a8b7d --- /dev/null +++ b/WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsDataAccessInstaller.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace WotBlitzStatisticsPro.DataAccess +{ + public static class WotBlitzStatisticsDataAccessInstaller + { + public static void ConfigureServices(IServiceCollection services) + { + services.AddTransient(); + } + + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsPro.DataAccess.csproj b/WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsPro.DataAccess.csproj new file mode 100644 index 0000000..adf42e1 --- /dev/null +++ b/WotBlitzStatisticsPro.DataAccess/WotBlitzStatisticsPro.DataAccess.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.1 + + + + + + + + + + + + diff --git a/WotBlitzStatisticsPro.GraphQl/MongoSettings.cs b/WotBlitzStatisticsPro.GraphQl/MongoSettings.cs new file mode 100644 index 0000000..06b7629 --- /dev/null +++ b/WotBlitzStatisticsPro.GraphQl/MongoSettings.cs @@ -0,0 +1,10 @@ +using WotBlitzStatisticsPro.Common; + +namespace WotBlitzStatisticsPro.GraphQl +{ + public class MongoSettings : IMongoSettings + { + public string ConnectionString { get; set; } + public string DatabaseName { get; set; } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.GraphQl/Startup.cs b/WotBlitzStatisticsPro.GraphQl/Startup.cs index 35f1c9d..a5861d9 100644 --- a/WotBlitzStatisticsPro.GraphQl/Startup.cs +++ b/WotBlitzStatisticsPro.GraphQl/Startup.cs @@ -29,7 +29,11 @@ namespace WotBlitzStatisticsPro.GraphQl var wgApiConfig = new WargamingApiSettings(); Configuration.GetSection("WargamingApi").Bind(wgApiConfig); + var mongoConfig = new MongoSettings(); + Configuration.GetSection("Mongo").Bind(mongoConfig); + services.AddSingleton(wgApiConfig); + services.AddSingleton(mongoConfig); WotBlitzStatisticsLogicInstaller.ConfigureServices(services); // Global data loader - caches data between requests diff --git a/WotBlitzStatisticsPro.GraphQl/appsettings.json b/WotBlitzStatisticsPro.GraphQl/appsettings.json index 69235aa..38983fc 100644 --- a/WotBlitzStatisticsPro.GraphQl/appsettings.json +++ b/WotBlitzStatisticsPro.GraphQl/appsettings.json @@ -10,5 +10,9 @@ "WargamingApi": { "ApplicationId": "e6bb7a6cd1b7da3ca5697f97072d2176" - } + }, + "Mongo": { + "ConnectionString": "mongodb://root:seCurePwd12!@localhost:27017/?authSource=admin", + "DatabaseName": "WotBlitzStatisticsPro" + } } diff --git a/WotBlitzStatisticsPro.Logic/Dictionaries/StaticDictionariesUpdater.cs b/WotBlitzStatisticsPro.Logic/Dictionaries/StaticDictionariesUpdater.cs index bc5e4bb..ca1b8f0 100644 --- a/WotBlitzStatisticsPro.Logic/Dictionaries/StaticDictionariesUpdater.cs +++ b/WotBlitzStatisticsPro.Logic/Dictionaries/StaticDictionariesUpdater.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using AutoMapper; using WotBlitzStatisticsPro.Common.Dictionaries; using WotBlitzStatisticsPro.Common.Model; +using WotBlitzStatisticsPro.DataAccess; using WotBlitzStatisticsPro.WgApiClient; using WotBlitzStatisticsPro.WgApiClient.Model; @@ -13,13 +14,16 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries public class StaticDictionariesUpdater : IDictionaryUpdater { private readonly IWargamingDictionariesApiClient _wargamingDictionariesApiClient; + private readonly IDictionariesDataAccessor _dataAccessor; private readonly IMapper _mapper; public StaticDictionariesUpdater( IWargamingDictionariesApiClient wargamingDictionariesApiClient, + IDictionariesDataAccessor dataAccessor, IMapper mapper) { _wargamingDictionariesApiClient = wargamingDictionariesApiClient; + _dataAccessor = dataAccessor; _mapper = mapper; } public async Task Update() @@ -31,11 +35,20 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries clanRoles, achievementsSections) = await GetAndMapDictionaries(); - // ToDo: Save dictionary to Mongo + await _dataAccessor.UpdateLanguages(languages); + await _dataAccessor.UpdateNations(nations); + await _dataAccessor.UpdateVehicleTypes(vehicleTypes); + await _dataAccessor.UpdateClanRoles(clanRoles); + await _dataAccessor.UpdateAchievementsSections(achievementsSections); // ToDo: create unit tests - throw new System.NotImplementedException(); + return new UpdateDictionariesResponseItem + { + DictionaryType = DictionaryType.StaticDictionaries, + Description = + $"Updated {languages.Count} items in Languages dictionary; {nations.Count} items in Nations dictionary; {vehicleTypes.Count} items in VehicleTypes dictionary; {clanRoles.Count} items in ClanRoles dictionary; {achievementsSections.Count} items in AchievementsSections dictionary" + }; } private async Task<( @@ -86,12 +99,13 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries { destinationItem = new NationDictionary { - NationId = source.Key, NationNames = new Dictionary() + NationId = source.Key, NationNames = new List() }; destinationDictionary.Add(destinationItem); } - destinationItem.NationNames[requestLanguage] = source.Value; + destinationItem.NationNames.Add( + new LocalizableString {Language = requestLanguage, Value = source.Value}); } } @@ -107,12 +121,13 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries { destinationItem = new VehicleTypeDictionary { - VehicleTypeId = source.Key, VehicleTypeNames = new Dictionary() + VehicleTypeId = source.Key, VehicleTypeNames = new List() }; destinationDictionary.Add(destinationItem); } - destinationItem.VehicleTypeNames[requestLanguage] = source.Value; + destinationItem.VehicleTypeNames.Add( + new LocalizableString { Language = requestLanguage, Value = source.Value }); } } @@ -128,12 +143,13 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries { destinationItem = new ClanRoleDictionary { - ClanRoleId = source.Key, ClanRoleNames = new Dictionary() + ClanRoleId = source.Key, ClanRoleNames = new List() }; destinationDictionary.Add(destinationItem); } - destinationItem.ClanRoleNames[requestLanguage] = source.Value; + destinationItem.ClanRoleNames.Add( + new LocalizableString { Language = requestLanguage, Value = source.Value }); } } @@ -152,12 +168,13 @@ namespace WotBlitzStatisticsPro.Logic.Dictionaries { AchievementSectionId = section.Key, Order = Convert.ToInt32(section.Value.Order), - AchievementSectionNames = new Dictionary() + AchievementSectionNames = new List() }; destinationDictionary.Add(destinationItem); } - destinationItem.AchievementSectionNames[requestLanguage] = section.Value.Name; + destinationItem.AchievementSectionNames.Add( + new LocalizableString { Language = requestLanguage, Value = section.Value.Name }); } } } diff --git a/WotBlitzStatisticsPro.Logic/WargamingDictionaries.cs b/WotBlitzStatisticsPro.Logic/WargamingDictionaries.cs index 940458b..2d2548a 100644 --- a/WotBlitzStatisticsPro.Logic/WargamingDictionaries.cs +++ b/WotBlitzStatisticsPro.Logic/WargamingDictionaries.cs @@ -24,7 +24,10 @@ namespace WotBlitzStatisticsPro.Logic if ((updateDictionariesRequest.DictionaryTypes & dictionaryType) != 0) { var dictionaryUpdater = _dictionaryUpdaterFactoryMethod(dictionaryType); - response.Add(await dictionaryUpdater.Update()); + if (dictionaryUpdater != null) + { + response.Add(await dictionaryUpdater.Update()); + } } } diff --git a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs index 8e6c430..a69235c 100644 --- a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs +++ b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs @@ -2,6 +2,7 @@ using AutoMapper; using Microsoft.Extensions.DependencyInjection; using WotBlitzStatisticsPro.Common.Model; +using WotBlitzStatisticsPro.DataAccess; using WotBlitzStatisticsPro.Logic.Dictionaries; using WotBlitzStatisticsPro.WgApiClient; @@ -14,6 +15,7 @@ namespace WotBlitzStatisticsPro.Logic public static void ConfigureServices(IServiceCollection services) { ConfigureDictionariesFactory(services); + WotBlitzStatisticsDataAccessInstaller.ConfigureServices(services); services.AddAutoMapper(typeof(WotBlitzStatisticsLogicInstaller)); services.AddHttpClient(); services.AddHttpClient(); @@ -38,8 +40,7 @@ namespace WotBlitzStatisticsPro.Logic case DictionaryType.Vehicles: return serviceProvider.GetService(); default: - throw new KeyNotFoundException( - $"Unable to find service for dictionary type '{dictionaryType}'"); + return null; } }); } diff --git a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsPro.Logic.csproj b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsPro.Logic.csproj index a8417a4..6dfd916 100644 --- a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsPro.Logic.csproj +++ b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsPro.Logic.csproj @@ -13,6 +13,7 @@ + diff --git a/WotBlitzStatisticsPro.sln b/WotBlitzStatisticsPro.sln index b74c5a4..052f0de 100644 --- a/WotBlitzStatisticsPro.sln +++ b/WotBlitzStatisticsPro.sln @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WotBlitzStatisticsPro.Logic EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WotBlitzStatisticsPro.GraphQl", "WotBlitzStatisticsPro.GraphQl\WotBlitzStatisticsPro.GraphQl.csproj", "{921E0CBA-5696-4BB3-A547-78F599B1479B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WotBlitzStatisticsPro.DataAccess", "WotBlitzStatisticsPro.DataAccess\WotBlitzStatisticsPro.DataAccess.csproj", "{19B1EDE4-1B83-49E2-A666-6CFE3A4A732E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,6 +37,10 @@ Global {921E0CBA-5696-4BB3-A547-78F599B1479B}.Debug|Any CPU.Build.0 = Debug|Any CPU {921E0CBA-5696-4BB3-A547-78F599B1479B}.Release|Any CPU.ActiveCfg = Release|Any CPU {921E0CBA-5696-4BB3-A547-78F599B1479B}.Release|Any CPU.Build.0 = Release|Any CPU + {19B1EDE4-1B83-49E2-A666-6CFE3A4A732E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19B1EDE4-1B83-49E2-A666-6CFE3A4A732E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19B1EDE4-1B83-49E2-A666-6CFE3A4A732E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19B1EDE4-1B83-49E2-A666-6CFE3A4A732E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -42,6 +48,7 @@ Global GlobalSection(NestedProjects) = preSolution {E1AB7997-C2A1-433B-A4F5-F8E9C4B73515} = {5095AE8F-F1D4-4BC0-95FD-B3DB0D3AED15} {A79103B3-4F04-4090-803E-B7AABFCC93B1} = {5095AE8F-F1D4-4BC0-95FD-B3DB0D3AED15} + {19B1EDE4-1B83-49E2-A666-6CFE3A4A732E} = {5095AE8F-F1D4-4BC0-95FD-B3DB0D3AED15} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {295179CC-53B9-4A2F-8051-A6B033EED16E}