Browse Source

removed sql delayed writer in favor of prepared statements

Luke Pulverenti 12 năm trước cách đây
mục cha
commit
e01202030d

+ 0 - 1
MediaBrowser.Controller/Providers/TV/RemoteSeasonProvider.cs

@@ -279,7 +279,6 @@ namespace MediaBrowser.Controller.Providers.TV
                     n = n.SelectSingleNode("./BannerPath");
                     n = n.SelectSingleNode("./BannerPath");
                     if (n != null)
                     if (n != null)
                     {
                     {
-                        if (season.BackdropImagePaths == null) season.BackdropImagePaths = new List<string>();
                         season.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "backdrop" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
                         season.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "backdrop" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
                     }
                     }
                 }
                 }

+ 1 - 1
MediaBrowser.Controller/Providers/TV/RemoteSeriesProvider.cs

@@ -525,7 +525,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
 
             if (series.BackdropImagePaths.Count < ConfigurationManager.Configuration.MaxBackdrops)
             if (series.BackdropImagePaths.Count < ConfigurationManager.Configuration.MaxBackdrops)
             {
             {
-                var bdNo = 0;
+                var bdNo = series.BackdropImagePaths.Count;
                 var xmlNodeList = images.SelectNodes("//Banner[BannerType='fanart']");
                 var xmlNodeList = images.SelectNodes("//Banner[BannerType='fanart']");
                 if (xmlNodeList != null)
                 if (xmlNodeList != null)
                 {
                 {

+ 3 - 15
MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs

@@ -33,18 +33,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
             }
             }
         }
         }
 
 
-        /// <summary>
-        /// Gets a value indicating whether [enable delayed commands].
-        /// </summary>
-        /// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
-        protected override bool EnableDelayedCommands
-        {
-            get
-            {
-                return false;
-            }
-        }
-
         /// <summary>
         /// <summary>
         /// The _json serializer
         /// The _json serializer
         /// </summary>
         /// </summary>
@@ -132,13 +120,13 @@ namespace MediaBrowser.Server.Implementations.Sqlite
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "replace into displaypreferences (id, data) values (@1, @2)";
                 cmd.CommandText = "replace into displaypreferences (id, data) values (@1, @2)";
                 cmd.AddParam("@1", displayPreferences.Id);
                 cmd.AddParam("@1", displayPreferences.Id);
                 cmd.AddParam("@2", serialized);
                 cmd.AddParam("@2", serialized);
 
 
-                using (var tran = connection.BeginTransaction())
+                using (var tran = Connection.BeginTransaction())
                 {
                 {
                     try
                     try
                     {
                     {
@@ -174,7 +162,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 throw new ArgumentNullException("displayPreferencesId");
                 throw new ArgumentNullException("displayPreferencesId");
             }
             }
 
 
-            var cmd = connection.CreateCommand();
+            var cmd = Connection.CreateCommand();
             cmd.CommandText = "select data from displaypreferences where id = @id";
             cmd.CommandText = "select data from displaypreferences where id = @id";
 
 
             var idParam = cmd.Parameters.Add("@id", DbType.Guid);
             var idParam = cmd.Parameters.Add("@id", DbType.Guid);

+ 142 - 29
MediaBrowser.Server.Implementations/Sqlite/SQLiteItemRepository.cs

@@ -8,6 +8,7 @@ using MediaBrowser.Server.Implementations.Reflection;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Data;
 using System.Data;
+using System.Data.SQLite;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Threading;
 using System.Threading;
@@ -53,6 +54,19 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// </summary>
         /// </summary>
         private readonly IApplicationPaths _appPaths;
         private readonly IApplicationPaths _appPaths;
 
 
+        /// <summary>
+        /// The _save item command
+        /// </summary>
+        private SQLiteCommand _saveItemCommand;
+        /// <summary>
+        /// The _delete children command
+        /// </summary>
+        private SQLiteCommand _deleteChildrenCommand;
+        /// <summary>
+        /// The _save children command
+        /// </summary>
+        private SQLiteCommand _saveChildrenCommand;
+
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="SQLiteUserDataRepository" /> class.
         /// Initializes a new instance of the <see cref="SQLiteUserDataRepository" /> class.
         /// </summary>
         /// </summary>
@@ -100,6 +114,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                                };
                                };
 
 
             RunQueries(queries);
             RunQueries(queries);
+
+            PrepareStatements();
         }
         }
 
 
         //cascade delete triggers
         //cascade delete triggers
@@ -116,6 +132,39 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                     DELETE FROM children WHERE children.child = old.child;
                     DELETE FROM children WHERE children.child = old.child;
                 END";
                 END";
 
 
+        /// <summary>
+        /// The _write lock
+        /// </summary>
+        private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1,1);
+
+        /// <summary>
+        /// Prepares the statements.
+        /// </summary>
+        private void PrepareStatements()
+        {
+            _saveItemCommand = new SQLiteCommand
+            {
+                CommandText = "replace into items (guid, obj_type, data) values (@1, @2, @3)"
+            };
+
+            _saveItemCommand.Parameters.Add(new SQLiteParameter("@1"));
+            _saveItemCommand.Parameters.Add(new SQLiteParameter("@2"));
+            _saveItemCommand.Parameters.Add(new SQLiteParameter("@3"));
+
+            _deleteChildrenCommand = new SQLiteCommand
+            {
+                CommandText = "delete from children where guid = @guid"
+            };
+            _deleteChildrenCommand.Parameters.Add(new SQLiteParameter("@guid"));
+
+            _saveChildrenCommand = new SQLiteCommand
+            {
+                CommandText = "replace into children (guid, child) values (@guid, @child)"
+            };
+            _saveChildrenCommand.Parameters.Add(new SQLiteParameter("@guid"));
+            _saveChildrenCommand.Parameters.Add(new SQLiteParameter("@child"));
+        }
+
         /// <summary>
         /// <summary>
         /// Save a standard item in the repo
         /// Save a standard item in the repo
         /// </summary>
         /// </summary>
@@ -123,7 +172,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         /// <exception cref="System.ArgumentNullException">item</exception>
         /// <exception cref="System.ArgumentNullException">item</exception>
-        public Task SaveItem(BaseItem item, CancellationToken cancellationToken)
+        public async Task SaveItem(BaseItem item, CancellationToken cancellationToken)
         {
         {
             if (item == null)
             if (item == null)
             {
             {
@@ -137,19 +186,51 @@ namespace MediaBrowser.Server.Implementations.Sqlite
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            return Task.Run(() =>
+            var serialized = _jsonSerializer.SerializeToBytes(item);
+
+            await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+            SQLiteTransaction transaction = null;
+
+            try
             {
             {
-                var serialized = _jsonSerializer.SerializeToBytes(item);
+                transaction = Connection.BeginTransaction();
 
 
-                cancellationToken.ThrowIfCancellationRequested();
+                _saveItemCommand.Parameters[0].Value = item.Id;
+                _saveItemCommand.Parameters[1].Value = item.GetType().FullName;
+                _saveItemCommand.Parameters[2].Value = serialized;
 
 
-                var cmd = connection.CreateCommand();
-                cmd.CommandText = "replace into items (guid, obj_type, data) values (@1, @2, @3)";
-                cmd.AddParam("@1", item.Id);
-                cmd.AddParam("@2", item.GetType().FullName);
-                cmd.AddParam("@3", serialized);
-                QueueCommand(cmd);
-            });
+                _saveItemCommand.Transaction = transaction;
+
+                await _saveItemCommand.ExecuteNonQueryAsync(cancellationToken);
+
+                transaction.Commit();
+            }
+            catch (OperationCanceledException)
+            {
+                if (transaction != null)
+                {
+                    transaction.Rollback();
+                }
+            }
+            catch (Exception e)
+            {
+                Logger.ErrorException("Failed to save item:", e);
+
+                if (transaction != null)
+                {
+                    transaction.Rollback();
+                }
+            }
+            finally
+            {
+                if (transaction != null)
+                {
+                    transaction.Dispose();
+                }
+
+                _writeLock.Release();
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -157,6 +238,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// </summary>
         /// </summary>
         /// <param name="id">The id.</param>
         /// <param name="id">The id.</param>
         /// <returns>BaseItem.</returns>
         /// <returns>BaseItem.</returns>
+        /// <exception cref="System.ArgumentNullException">id</exception>
         /// <exception cref="System.ArgumentException"></exception>
         /// <exception cref="System.ArgumentException"></exception>
         public BaseItem GetItem(Guid id)
         public BaseItem GetItem(Guid id)
         {
         {
@@ -189,6 +271,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// </summary>
         /// </summary>
         /// <param name="id">The id.</param>
         /// <param name="id">The id.</param>
         /// <returns>BaseItem.</returns>
         /// <returns>BaseItem.</returns>
+        /// <exception cref="System.ArgumentNullException">id</exception>
         /// <exception cref="System.ArgumentException"></exception>
         /// <exception cref="System.ArgumentException"></exception>
         protected BaseItem RetrieveItemInternal(Guid id)
         protected BaseItem RetrieveItemInternal(Guid id)
         {
         {
@@ -197,7 +280,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 throw new ArgumentNullException("id");
                 throw new ArgumentNullException("id");
             }
             }
 
 
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select obj_type,data from items where guid = @guid";
                 cmd.CommandText = "select obj_type,data from items where guid = @guid";
                 var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);
                 var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);
@@ -240,7 +323,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 throw new ArgumentNullException();
                 throw new ArgumentNullException();
             }
             }
 
 
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select obj_type,data from items where guid in (select child from children where guid = @guid)";
                 cmd.CommandText = "select obj_type,data from items where guid in (select child from children where guid = @guid)";
                 var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);
                 var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);
@@ -281,7 +364,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         /// <exception cref="System.ArgumentNullException">id</exception>
         /// <exception cref="System.ArgumentNullException">id</exception>
-        public Task SaveChildren(Guid id, IEnumerable<BaseItem> children, CancellationToken cancellationToken)
+        public async Task SaveChildren(Guid id, IEnumerable<BaseItem> children, CancellationToken cancellationToken)
         {
         {
             if (id == Guid.Empty)
             if (id == Guid.Empty)
             {
             {
@@ -300,27 +383,57 @@ namespace MediaBrowser.Server.Implementations.Sqlite
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            return Task.Run(() =>
-            {
-                var cmd = connection.CreateCommand();
+            await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+            SQLiteTransaction transaction = null;
 
 
-                cmd.CommandText = "delete from children where guid = @guid";
-                cmd.AddParam("@guid", id);
+            try
+            {
+                transaction = Connection.BeginTransaction();
 
 
-                QueueCommand(cmd);
+                // Delete exising children
+                _deleteChildrenCommand.Parameters[0].Value = id;
+                _deleteChildrenCommand.Transaction = transaction;
+                await _deleteChildrenCommand.ExecuteNonQueryAsync(cancellationToken);
 
 
+                // Save new children
                 foreach (var child in children)
                 foreach (var child in children)
                 {
                 {
-                    var guid = child.Id;
-                    cmd = connection.CreateCommand();
-                    cmd.AddParam("@guid", id);
-                    cmd.CommandText = "replace into children (guid, child) values (@guid, @child)";
-                    var childParam = cmd.Parameters.Add("@child", DbType.Guid);
-
-                    childParam.Value = guid;
-                    QueueCommand(cmd);
+                    _saveChildrenCommand.Transaction = transaction;
+                    
+                    _saveChildrenCommand.Parameters[0].Value = id;
+                    _saveChildrenCommand.Parameters[1].Value = child.Id;
+
+                    await _saveChildrenCommand.ExecuteNonQueryAsync(cancellationToken);
+                }
+
+                transaction.Commit();
+            }
+            catch (OperationCanceledException)
+            {
+                if (transaction != null)
+                {
+                    transaction.Rollback();
                 }
                 }
-            });
+            }
+            catch (Exception e)
+            {
+                Logger.ErrorException("Failed to save item:", e);
+
+                if (transaction != null)
+                {
+                    transaction.Rollback();
+                }
+            }
+            finally
+            {
+                if (transaction != null)
+                {
+                    transaction.Dispose();
+                }
+
+                _writeLock.Release();
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 14 - 151
MediaBrowser.Server.Implementations/Sqlite/SQLiteRepository.cs

@@ -18,24 +18,11 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// <summary>
         /// <summary>
         /// The db file name
         /// The db file name
         /// </summary>
         /// </summary>
-        protected string dbFileName;
+        protected string DbFileName;
         /// <summary>
         /// <summary>
         /// The connection
         /// The connection
         /// </summary>
         /// </summary>
-        protected SQLiteConnection connection;
-        /// <summary>
-        /// The delayed commands
-        /// </summary>
-        protected ConcurrentQueue<SQLiteCommand> delayedCommands = new ConcurrentQueue<SQLiteCommand>();
-        /// <summary>
-        /// The flush interval
-        /// </summary>
-        private const int FlushInterval = 2000;
-
-        /// <summary>
-        /// The flush timer
-        /// </summary>
-        private Timer FlushTimer;
+        protected SQLiteConnection Connection;
 
 
         /// <summary>
         /// <summary>
         /// Gets the logger.
         /// Gets the logger.
@@ -43,18 +30,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// <value>The logger.</value>
         /// <value>The logger.</value>
         protected ILogger Logger { get; private set; }
         protected ILogger Logger { get; private set; }
 
 
-        /// <summary>
-        /// Gets a value indicating whether [enable delayed commands].
-        /// </summary>
-        /// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
-        protected virtual bool EnableDelayedCommands
-        {
-            get
-            {
-                return true;
-            }
-        }
-
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="SqliteRepository" /> class.
         /// Initializes a new instance of the <see cref="SqliteRepository" /> class.
         /// </summary>
         /// </summary>
@@ -83,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 throw new ArgumentNullException("dbPath");
                 throw new ArgumentNullException("dbPath");
             }
             }
 
 
-            dbFileName = dbPath;
+            DbFileName = dbPath;
             var connectionstr = new SQLiteConnectionStringBuilder
             var connectionstr = new SQLiteConnectionStringBuilder
             {
             {
                 PageSize = 4096,
                 PageSize = 4096,
@@ -93,15 +68,9 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 JournalMode = SQLiteJournalModeEnum.Memory
                 JournalMode = SQLiteJournalModeEnum.Memory
             };
             };
 
 
-            connection = new SQLiteConnection(connectionstr.ConnectionString);
+            Connection = new SQLiteConnection(connectionstr.ConnectionString);
 
 
-            await connection.OpenAsync().ConfigureAwait(false);
-
-            if (EnableDelayedCommands)
-            {
-                // Run once
-                FlushTimer = new Timer(Flush, null, TimeSpan.FromMilliseconds(FlushInterval), TimeSpan.FromMilliseconds(-1));
-            }
+            await Connection.OpenAsync().ConfigureAwait(false);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -117,11 +86,11 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 throw new ArgumentNullException("queries");
                 throw new ArgumentNullException("queries");
             }
             }
 
 
-            using (var tran = connection.BeginTransaction())
+            using (var tran = Connection.BeginTransaction())
             {
             {
                 try
                 try
                 {
                 {
-                    using (var cmd = connection.CreateCommand())
+                    using (var cmd = Connection.CreateCommand())
                     {
                     {
                         foreach (var query in queries)
                         foreach (var query in queries)
                         {
                         {
@@ -165,26 +134,15 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 {
                 {
                     lock (_disposeLock)
                     lock (_disposeLock)
                     {
                     {
-                        if (connection != null)
+                        if (Connection != null)
                         {
                         {
-                            if (EnableDelayedCommands)
+                            if (Connection.IsOpen())
                             {
                             {
-                                FlushOnDispose();
+                                Connection.Close();
                             }
                             }
 
 
-                            if (connection.IsOpen())
-                            {
-                                connection.Close();
-                            }
-
-                            connection.Dispose();
-                            connection = null;
-                        }
-
-                        if (FlushTimer != null)
-                        {
-                            FlushTimer.Dispose();
-                            FlushTimer = null;
+                            Connection.Dispose();
+                            Connection = null;
                         }
                         }
                     }
                     }
                 }
                 }
@@ -195,101 +153,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
             }
             }
         }
         }
 
 
-        /// <summary>
-        /// Flushes the on dispose.
-        /// </summary>
-        private void FlushOnDispose()
-        {
-            // If we're not already flushing, do it now
-            if (!_isFlushing)
-            {
-                Flush(null);
-            }
-
-            // Don't dispose in the middle of a flush
-            while (_isFlushing)
-            {
-                Thread.Sleep(25);
-            }
-        }
-
-        /// <summary>
-        /// Queues the command.
-        /// </summary>
-        /// <param name="cmd">The CMD.</param>
-        /// <exception cref="System.ArgumentNullException">cmd</exception>
-        protected void QueueCommand(SQLiteCommand cmd)
-        {
-            if (cmd == null)
-            {
-                throw new ArgumentNullException("cmd");
-            }
-
-            delayedCommands.Enqueue(cmd);
-        }
-
-        /// <summary>
-        /// The is flushing
-        /// </summary>
-        private bool _isFlushing;
-
-        /// <summary>
-        /// Flushes the specified sender.
-        /// </summary>
-        /// <param name="sender">The sender.</param>
-        private void Flush(object sender)
-        {
-            // Cannot call Count on a ConcurrentQueue since it's an O(n) operation
-            // Use IsEmpty instead
-            if (delayedCommands.IsEmpty)
-            {
-                FlushTimer.Change(TimeSpan.FromMilliseconds(FlushInterval), TimeSpan.FromMilliseconds(-1));
-                return;
-            }
-
-            if (_isFlushing)
-            {
-                return;
-            }
-
-            _isFlushing = true;
-            var numCommands = 0;
-
-            using (var tran = connection.BeginTransaction())
-            {
-                try
-                {
-                    while (!delayedCommands.IsEmpty)
-                    {
-                        SQLiteCommand command;
-
-                        delayedCommands.TryDequeue(out command);
-
-                        command.Connection = connection;
-                        command.Transaction = tran;
-
-                        command.ExecuteNonQuery();
-
-                        command.Dispose();
-
-                        numCommands++;
-                    }
-
-                    tran.Commit();
-                }
-                catch (Exception e)
-                {
-                    Logger.ErrorException("Failed to commit transaction.", e);
-                    tran.Rollback();
-                }
-            }
-
-            Logger.Debug("SQL Delayed writer executed " + numCommands + " commands");
-
-            FlushTimer.Change(TimeSpan.FromMilliseconds(FlushInterval), TimeSpan.FromMilliseconds(-1));
-            _isFlushing = false;
-        }
-
         /// <summary>
         /// <summary>
         /// Executes the command.
         /// Executes the command.
         /// </summary>
         /// </summary>
@@ -303,11 +166,11 @@ namespace MediaBrowser.Server.Implementations.Sqlite
                 throw new ArgumentNullException("cmd");
                 throw new ArgumentNullException("cmd");
             }
             }
 
 
-            using (var tran = connection.BeginTransaction())
+            using (var tran = Connection.BeginTransaction())
             {
             {
                 try
                 try
                 {
                 {
-                    cmd.Connection = connection;
+                    cmd.Connection = Connection;
                     cmd.Transaction = tran;
                     cmd.Transaction = tran;
 
 
                     await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
                     await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);

+ 3 - 15
MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs

@@ -36,18 +36,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
             }
             }
         }
         }
 
 
-        /// <summary>
-        /// Gets a value indicating whether [enable delayed commands].
-        /// </summary>
-        /// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
-        protected override bool EnableDelayedCommands
-        {
-            get
-            {
-                return false;
-            }
-        }
-
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IJsonSerializer _jsonSerializer;
 
 
         /// <summary>
         /// <summary>
@@ -184,14 +172,14 @@ namespace MediaBrowser.Server.Implementations.Sqlite
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "replace into userdata (key, userId, data) values (@1, @2, @3)";
                 cmd.CommandText = "replace into userdata (key, userId, data) values (@1, @2, @3)";
                 cmd.AddParam("@1", key);
                 cmd.AddParam("@1", key);
                 cmd.AddParam("@2", userId);
                 cmd.AddParam("@2", userId);
                 cmd.AddParam("@3", serialized);
                 cmd.AddParam("@3", serialized);
 
 
-                using (var tran = connection.BeginTransaction())
+                using (var tran = Connection.BeginTransaction())
                 {
                 {
                     try
                     try
                     {
                     {
@@ -247,7 +235,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// <returns>Task{UserItemData}.</returns>
         /// <returns>Task{UserItemData}.</returns>
         private async Task<UserItemData> RetrieveUserData(Guid userId, string key)
         private async Task<UserItemData> RetrieveUserData(Guid userId, string key)
         {
         {
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select data from userdata where key = @key and userId=@userId";
                 cmd.CommandText = "select data from userdata where key = @key and userId=@userId";
 
 

+ 4 - 16
MediaBrowser.Server.Implementations/Sqlite/SQLiteUserRepository.cs

@@ -45,18 +45,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// </summary>
         /// </summary>
         private readonly IApplicationPaths _appPaths;
         private readonly IApplicationPaths _appPaths;
 
 
-        /// <summary>
-        /// Gets a value indicating whether [enable delayed commands].
-        /// </summary>
-        /// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
-        protected override bool EnableDelayedCommands
-        {
-            get
-            {
-                return false;
-            }
-        }
-
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="SQLiteUserDataRepository" /> class.
         /// Initializes a new instance of the <see cref="SQLiteUserDataRepository" /> class.
         /// </summary>
         /// </summary>
@@ -127,13 +115,13 @@ namespace MediaBrowser.Server.Implementations.Sqlite
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "replace into users (guid, data) values (@1, @2)";
                 cmd.CommandText = "replace into users (guid, data) values (@1, @2)";
                 cmd.AddParam("@1", user.Id);
                 cmd.AddParam("@1", user.Id);
                 cmd.AddParam("@2", serialized);
                 cmd.AddParam("@2", serialized);
 
 
-                using (var tran = connection.BeginTransaction())
+                using (var tran = Connection.BeginTransaction())
                 {
                 {
                     try
                     try
                     {
                     {
@@ -162,7 +150,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
         /// <returns>IEnumerable{User}.</returns>
         /// <returns>IEnumerable{User}.</returns>
         public IEnumerable<User> RetrieveAllUsers()
         public IEnumerable<User> RetrieveAllUsers()
         {
         {
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "select data from users";
                 cmd.CommandText = "select data from users";
 
 
@@ -201,7 +189,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
-            using (var cmd = connection.CreateCommand())
+            using (var cmd = Connection.CreateCommand())
             {
             {
                 cmd.CommandText = "delete from users where guid=@guid";
                 cmd.CommandText = "delete from users where guid=@guid";
                 var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);
                 var guidParam = cmd.Parameters.Add("@guid", DbType.Guid);