UserDataMigration.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using MediaBrowser.Controller.Entities;
  2. using MediaBrowser.Model.Logging;
  3. using MediaBrowser.Model.Serialization;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Data;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Threading.Tasks;
  10. namespace MediaBrowser.Server.Implementations.Persistence
  11. {
  12. public static class UserDataMigration
  13. {
  14. /// <summary>
  15. /// Migrates the specified old file.
  16. /// </summary>
  17. /// <param name="oldFile">The old file.</param>
  18. /// <param name="newDatabase">The new database.</param>
  19. /// <param name="logger">The logger.</param>
  20. /// <param name="json">The json.</param>
  21. /// <returns>Task.</returns>
  22. public static async Task Migrate(string oldFile, IDbConnection newDatabase, ILogger logger, IJsonSerializer json)
  23. {
  24. var oldDb = await SqliteExtensions.ConnectToDb(oldFile).ConfigureAwait(false);
  25. using (oldDb)
  26. {
  27. IDbTransaction transaction = null;
  28. var data = GetAllUserData(oldDb, json).ToList();
  29. try
  30. {
  31. transaction = newDatabase.BeginTransaction();
  32. foreach (var userdata in data)
  33. {
  34. PersistUserData(userdata, newDatabase, transaction);
  35. }
  36. transaction.Commit();
  37. }
  38. catch (OperationCanceledException)
  39. {
  40. if (transaction != null)
  41. {
  42. transaction.Rollback();
  43. }
  44. throw;
  45. }
  46. catch (Exception e)
  47. {
  48. logger.ErrorException("Failed to save user data:", e);
  49. if (transaction != null)
  50. {
  51. transaction.Rollback();
  52. }
  53. throw;
  54. }
  55. finally
  56. {
  57. if (transaction != null)
  58. {
  59. transaction.Dispose();
  60. }
  61. }
  62. }
  63. var backupFile = Path.Combine(Path.GetDirectoryName(oldFile), "userdata_v1.db.bak");
  64. if (File.Exists(backupFile))
  65. {
  66. File.Delete(backupFile);
  67. }
  68. File.Move(oldFile, backupFile);
  69. }
  70. /// <summary>
  71. /// Gets all user data.
  72. /// </summary>
  73. /// <param name="oldDatabase">The old database.</param>
  74. /// <param name="jsonSerializer">The json serializer.</param>
  75. /// <returns>IEnumerable{UserItemData}.</returns>
  76. private static IEnumerable<UserItemData> GetAllUserData(IDbConnection oldDatabase, IJsonSerializer jsonSerializer)
  77. {
  78. using (var cmd = oldDatabase.CreateCommand())
  79. {
  80. cmd.CommandText = "select userId,key,data from userdata";
  81. using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
  82. {
  83. while (reader.Read())
  84. {
  85. var userId = reader.GetGuid(0);
  86. var key = reader.GetString(1);
  87. using (var stream = reader.GetMemoryStream(2))
  88. {
  89. var userData = jsonSerializer.DeserializeFromStream<UserItemData>(stream);
  90. userData.UserId = userId;
  91. userData.Key = key;
  92. yield return userData;
  93. }
  94. }
  95. }
  96. }
  97. }
  98. /// <summary>
  99. /// Persists the user data.
  100. /// </summary>
  101. /// <param name="userData">The user data.</param>
  102. /// <param name="database">The database.</param>
  103. /// <param name="transaction">The transaction.</param>
  104. private static void PersistUserData(UserItemData userData, IDbConnection database, IDbTransaction transaction)
  105. {
  106. using (var cmd = database.CreateCommand())
  107. {
  108. cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate)";
  109. cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userData.Key;
  110. cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userData.UserId;
  111. cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating;
  112. cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played;
  113. cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount;
  114. cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite;
  115. cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks;
  116. cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate;
  117. cmd.Transaction = transaction;
  118. cmd.ExecuteNonQuery();
  119. }
  120. }
  121. }
  122. }