UpdateDatabaseFiles.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using Comal.Stores;
  2. using InABox.Configuration;
  3. using InABox.Core;
  4. using InABox.Database;
  5. using InABox.Database.SQLite;
  6. using InABox.Logging;
  7. using InABox.Wpf;
  8. using InABox.WPF;
  9. using PRSServices;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Data.Common;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. namespace PRSServer.Forms.Version9Update;
  18. public static class UpdateDatabaseFiles
  19. {
  20. public static bool UpdateDatabases(int targetMajorVersion)
  21. {
  22. try
  23. {
  24. Progress.ShowModal("Loading Data", progress =>
  25. {
  26. var sections = PRSService.GetConfiguration().LoadAll();
  27. var stores = CoreUtils.TypeList(
  28. AppDomain.CurrentDomain.GetAssemblies(),
  29. myType =>
  30. myType.IsClass
  31. && !myType.IsAbstract
  32. && !myType.IsGenericType
  33. && myType.GetInterfaces().Contains(typeof(IStore))
  34. ).ToArray();
  35. foreach (var section in sections.Where(x => x.Value.Type == ServerType.Database))
  36. {
  37. var properties = section.Value.DeserializeServerProperties();
  38. if (properties is not DatabaseServerProperties databaseProperties) continue;
  39. var factory = new SQLiteProviderFactory(databaseProperties.FileName);
  40. // Not starting the factory, since otherwise that will do bad things to the database if it is already version 9.
  41. // Instead, we just want to call a single SQL statement, really.
  42. var originalVersion = DbFactory.GetDatabaseVersion(factory);
  43. if (originalVersion.MajorVersion >= targetMajorVersion) continue;
  44. progress.Report($"Backing up database '{databaseProperties.Name}'");
  45. if (File.Exists(databaseProperties.FileName))
  46. {
  47. var directory = Path.GetDirectoryName(databaseProperties.FileName) ?? "";
  48. var originalFileName = Path.GetFileNameWithoutExtension(databaseProperties.FileName);
  49. var newFileName = Path.Combine(directory, $"{originalFileName}_{originalVersion}_backup.dbs");
  50. var i = 0;
  51. while (File.Exists(newFileName))
  52. {
  53. newFileName = Path.Combine(directory, $"{originalFileName}_{originalVersion}_backup_{i}.dbs");
  54. ++i;
  55. }
  56. File.Copy(databaseProperties.FileName, newFileName);
  57. }
  58. progress.Report($"Updating database '{databaseProperties.Name}' from version {originalVersion}");
  59. DbFactory.Stores = stores;
  60. DbFactory.DefaultStore = typeof(BaseStore<>);
  61. // Adding extra logger so that the SQL transactions are put in the right place.
  62. var logger = new LogFileLogger(DatabaseEngine.GetPath(section.Key), true);
  63. MainLogger.AddLogger(logger);
  64. factory = new SQLiteProviderFactory(databaseProperties.FileName);
  65. factory.Types = DbFactory.Entities.Where(x =>
  66. x.IsClass
  67. && !x.IsGenericType
  68. && x.IsSubclassOf(typeof(Entity))
  69. ).ToArray();
  70. DbFactory.ProviderFactory = factory;
  71. DbFactory.Start(); // Doing this will run all the update scripts.
  72. factory.InitializeNulls();
  73. var dbVersion = DbFactory.GetVersionSettings(factory);
  74. dbVersion.Version = new VersionNumber(9, 0).ToString();
  75. var result = factory.NewProvider(Logger.Main)
  76. .Query(Filter<GlobalSettings>.Where(x => x.Section).IsEqualTo(nameof(DatabaseVersion)))
  77. .Rows.FirstOrDefault()?.ToObject<GlobalSettings>() ?? new GlobalSettings() { Section = nameof(DatabaseVersion), Key = "" };
  78. result.OriginalValueList["Contents"] = result.Contents;
  79. result.Contents = Serialization.Serialize(dbVersion);
  80. factory.NewProvider(Logger.Main).Save(result);
  81. MainLogger.RemoveLogger(logger);
  82. }
  83. });
  84. return true;
  85. }
  86. catch(Exception e)
  87. {
  88. MessageWindow.ShowError($"An error occurred while updating database files.", e);
  89. return false;
  90. }
  91. }
  92. }