diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
index b0ce7bf7c6..2a904be0d9 100644
--- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using System.Collections.Generic;
+using MediaBrowser.Controller.Entities;
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -33,5 +34,22 @@ namespace MediaBrowser.Controller.Persistence
/// The key.
/// Task{UserItemData}.
UserItemData GetUserData(Guid userId, string key);
+
+ ///
+ /// Return all user data associated with the given user
+ ///
+ ///
+ ///
+ IEnumerable GetAllUserData(Guid userId);
+
+ ///
+ /// Save all user data associated with the given user
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task SaveAllUserData(Guid userId, IEnumerable userData, CancellationToken cancellationToken);
+
}
}
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
index 4e388b4b0e..92fdde60f4 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Configuration;
+using System.Collections.Generic;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Logging;
@@ -117,6 +118,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
return PersistUserData(userId, key, userData, cancellationToken);
}
+ public Task SaveAllUserData(Guid userId, IEnumerable userData, CancellationToken cancellationToken)
+ {
+ if (userData == null)
+ {
+ throw new ArgumentNullException("userData");
+ }
+ if (userId == Guid.Empty)
+ {
+ throw new ArgumentNullException("userId");
+ }
+
+ return PersistAllUserData(userId, userData, cancellationToken);
+ }
+
///
/// Persists the user data.
///
@@ -188,6 +203,79 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ ///
+ /// Persist all user data for the specified user
+ ///
+ ///
+ ///
+ ///
+ ///
+ private async Task PersistAllUserData(Guid userId, IEnumerable userData, CancellationToken cancellationToken)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ foreach (var userItemData in userData)
+ {
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate)";
+
+ cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userItemData.Key;
+ cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
+ cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userItemData.Rating;
+ cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userItemData.Played;
+ cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userItemData.PlayCount;
+ cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userItemData.IsFavorite;
+ cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userItemData.PlaybackPositionTicks;
+ cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userItemData.LastPlayedDate;
+
+ cmd.Transaction = transaction;
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to save user data:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
///
/// Gets the user data.
///
@@ -227,25 +315,72 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
if (reader.Read())
{
- if (!reader.IsDBNull(0))
- {
- userData.Rating = reader.GetDouble(0);
- }
+ ReadRow(reader, ref userData);
+ }
+ }
+
+ return userData;
+ }
+ }
+
+ ///
+ /// Return all user-data associated with the given user
+ ///
+ ///
+ ///
+ public IEnumerable GetAllUserData(Guid userId)
+ {
+ if (userId == Guid.Empty)
+ {
+ throw new ArgumentNullException("userId");
+ }
- userData.Played = reader.GetBoolean(1);
- userData.PlayCount = reader.GetInt32(2);
- userData.IsFavorite = reader.GetBoolean(3);
- userData.PlaybackPositionTicks = reader.GetInt64(4);
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,key from userdata where userId=@userId";
+
+ cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
- if (!reader.IsDBNull(5))
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ var userData = new UserItemData
{
- userData.LastPlayedDate = reader.GetDateTime(5).ToUniversalTime();
- }
+ UserId = userId,
+ };
+ ReadRow(reader, ref userData);
+ userData.Key = reader.GetString(6);
+ yield return userData;
}
}
- return userData;
}
+
+ }
+
+ ///
+ /// Read a row from the specified reader into the provided userData object
+ ///
+ ///
+ ///
+ private static void ReadRow(IDataReader reader, ref UserItemData userData)
+ {
+ if (!reader.IsDBNull(0))
+ {
+ userData.Rating = reader.GetDouble(0);
+ }
+
+ userData.Played = reader.GetBoolean(1);
+ userData.PlayCount = reader.GetInt32(2);
+ userData.IsFavorite = reader.GetBoolean(3);
+ userData.PlaybackPositionTicks = reader.GetInt64(4);
+
+ if (!reader.IsDBNull(5))
+ {
+ userData.LastPlayedDate = reader.GetDateTime(5).ToUniversalTime();
+ }
+
}
///