diff options
| author | Techywarrior <techywarrior@gmail.com> | 2013-04-02 13:07:55 -0700 |
|---|---|---|
| committer | Techywarrior <techywarrior@gmail.com> | 2013-04-02 13:07:55 -0700 |
| commit | 713afcf6755b15142244cad6b16f8d539bd12893 (patch) | |
| tree | d5d7479281f85fc47d24d8c95a2ce29a3a146d8b /MediaBrowser.Server.Implementations | |
| parent | c957f202cc1fefb174377b99495b329a6cb9ee72 (diff) | |
| parent | e2562879d86aafc1063e37bfd353c22309e8e237 (diff) | |
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
Diffstat (limited to 'MediaBrowser.Server.Implementations')
7 files changed, 261 insertions, 137 deletions
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs index edb227c799..6696039586 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs @@ -160,7 +160,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (exception != null) { - _logger.ErrorException("Error processing request", exception); + _logger.ErrorException("Error processing request for {0}", exception, req.RawUrl); if (!string.IsNullOrEmpty(exception.Message)) { diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 84055cea78..a57eb8eaa3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -124,15 +124,6 @@ namespace MediaBrowser.Server.Implementations.Library LazyInitializer.EnsureInitialized(ref _libraryItemsCache, ref _libraryItemsCacheInitialized, ref _libraryItemsCacheSyncLock, CreateLibraryItemsCache); return _libraryItemsCache; } - set - { - _libraryItemsCache = value; - - if (value == null) - { - _libraryItemsCacheInitialized = false; - } - } } /// <summary> @@ -267,10 +258,22 @@ namespace MediaBrowser.Server.Implementations.Library items.AddRange(specialFeatures); items.AddRange(localTrailers); - // Can't add these right now because there could be separate instances with the same id. - //items.AddRange(_userManager.Users.Select(i => i.RootFolder).Distinct().ToList()); + // Need to use DistinctBy Id because there could be multiple instances with the same id + // due to sharing the default library + var userRootFolders = _userManager.Users.Select(i => i.RootFolder) + .DistinctBy(i => i.Id) + .ToList(); + + items.AddRange(userRootFolders); - items.AddRange(_userManager.Users.SelectMany(i => i.RootFolder.Children).Where(i => !(i is BasePluginFolder)).Distinct().ToList()); + // Get all user collection folders + var userFolders = + _userManager.Users.SelectMany(i => i.RootFolder.Children) + .Where(i => !(i is BasePluginFolder)) + .DistinctBy(i => i.Id) + .ToList(); + + items.AddRange(userFolders); return new ConcurrentDictionary<Guid,BaseItem>(items.ToDictionary(i => i.Id)); } @@ -745,26 +748,6 @@ namespace MediaBrowser.Server.Implementations.Library } /// <summary> - /// Saves display preferences for a Folder - /// </summary> - /// <param name="user">The user.</param> - /// <param name="folder">The folder.</param> - /// <param name="data">The data.</param> - /// <returns>Task.</returns> - public Task SaveDisplayPreferencesForFolder(User user, Folder folder, DisplayPreferences data) - { - // Need to update all items with the same DisplayPreferencesId - foreach (var child in RootFolder.GetRecursiveChildren(user) - .OfType<Folder>() - .Where(i => i.DisplayPreferencesId == folder.DisplayPreferencesId)) - { - child.AddOrUpdateDisplayPreferences(user, data); - } - - return Kernel.DisplayPreferencesRepository.SaveDisplayPreferences(folder, CancellationToken.None); - } - - /// <summary> /// Gets the default view. /// </summary> /// <returns>IEnumerable{VirtualFolderInfo}.</returns> @@ -878,6 +861,7 @@ namespace MediaBrowser.Server.Implementations.Library var userComparer = (IUserBaseItemComparer)Activator.CreateInstance(comparer.GetType()); userComparer.User = user; + userComparer.UserManager = _userManager; return userComparer; } diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 49b2a3f18d..ca3c1fe7cf 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -5,8 +5,10 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Connectivity; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; @@ -98,6 +100,13 @@ namespace MediaBrowser.Server.Implementations.Library private IServerConfigurationManager ConfigurationManager { get; set; } /// <summary> + /// The _user data + /// </summary> + private readonly ConcurrentDictionary<string, Task<DisplayPreferences>> _displayPreferences = new ConcurrentDictionary<string, Task<DisplayPreferences>>(); + + private readonly ConcurrentDictionary<string, Task<UserItemData>> _userData = new ConcurrentDictionary<string, Task<UserItemData>>(); + + /// <summary> /// Initializes a new instance of the <see cref="UserManager" /> class. /// </summary> /// <param name="kernel">The kernel.</param> @@ -157,6 +166,63 @@ namespace MediaBrowser.Server.Implementations.Library #endregion /// <summary> + /// Gets the display preferences. + /// </summary> + /// <param name="userId">The user id.</param> + /// <param name="displayPreferencesId">The display preferences id.</param> + /// <returns>DisplayPreferences.</returns> + public Task<DisplayPreferences> GetDisplayPreferences(Guid userId, Guid displayPreferencesId) + { + var key = userId + displayPreferencesId.ToString(); + + return _displayPreferences.GetOrAdd(key, keyName => RetrieveDisplayPreferences(userId, displayPreferencesId)); + } + + /// <summary> + /// Retrieves the display preferences. + /// </summary> + /// <param name="userId">The user id.</param> + /// <param name="displayPreferencesId">The display preferences id.</param> + /// <returns>DisplayPreferences.</returns> + private async Task<DisplayPreferences> RetrieveDisplayPreferences(Guid userId, Guid displayPreferencesId) + { + var displayPreferences = await Kernel.Instance.DisplayPreferencesRepository.GetDisplayPreferences(userId, displayPreferencesId).ConfigureAwait(false); + + return displayPreferences ?? new DisplayPreferences(); + } + + /// <summary> + /// Saves display preferences for an item + /// </summary> + /// <param name="userId">The user id.</param> + /// <param name="displayPreferencesId">The display preferences id.</param> + /// <param name="displayPreferences">The display preferences.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + public async Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences, CancellationToken cancellationToken) + { + var key = userId + displayPreferencesId.ToString(); + + try + { + await Kernel.Instance.DisplayPreferencesRepository.SaveDisplayPreferences(userId, displayPreferencesId, + displayPreferences, + cancellationToken).ConfigureAwait(false); + + var newValue = Task.FromResult(displayPreferences); + + // Once it succeeds, put it into the dictionary to make it available to everyone else + _displayPreferences.AddOrUpdate(key, newValue, delegate { return newValue; }); + } + catch (Exception ex) + { + _logger.ErrorException("Error saving display preferences", ex); + + throw; + } + } + + /// <summary> /// Gets a User by Id /// </summary> /// <param name="id">The id.</param> @@ -588,10 +654,10 @@ namespace MediaBrowser.Server.Implementations.Library if (positionTicks.HasValue) { - var data = item.GetUserData(user, true); + var data = await GetUserData(user.Id, item.UserDataId).ConfigureAwait(false); UpdatePlayState(item, data, positionTicks.Value, false); - await SaveUserDataForItem(user, item, data).ConfigureAwait(false); + await SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None).ConfigureAwait(false); } EventHelper.QueueEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs @@ -626,7 +692,7 @@ namespace MediaBrowser.Server.Implementations.Library RemoveNowPlayingItemId(user, clientType, deviceId, deviceName, item); - var data = item.GetUserData(user, true); + var data = await GetUserData(user.Id, item.UserDataId).ConfigureAwait(false); if (positionTicks.HasValue) { @@ -639,7 +705,7 @@ namespace MediaBrowser.Server.Implementations.Library data.Played = true; } - await SaveUserDataForItem(user, item, data).ConfigureAwait(false); + await SaveUserData(user.Id, item.UserDataId, data, CancellationToken.None).ConfigureAwait(false); EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackProgressEventArgs { @@ -700,17 +766,57 @@ namespace MediaBrowser.Server.Implementations.Library } /// <summary> - /// Saves user data for an item + /// Saves display preferences for an item /// </summary> - /// <param name="user">The user.</param> - /// <param name="item">The item.</param> - /// <param name="data">The data.</param> - public Task SaveUserDataForItem(User user, BaseItem item, UserItemData data) + /// <param name="userId">The user id.</param> + /// <param name="userDataId">The user data id.</param> + /// <param name="userData">The user data.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + public async Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken) + { + var key = userId + userDataId.ToString(); + try + { + await Kernel.Instance.UserDataRepository.SaveUserData(userId, userDataId, userData, cancellationToken).ConfigureAwait(false); + + var newValue = Task.FromResult(userData); + + // Once it succeeds, put it into the dictionary to make it available to everyone else + _userData.AddOrUpdate(key, newValue, delegate { return newValue; }); + } + catch (Exception ex) + { + _logger.ErrorException("Error saving user data", ex); + + throw; + } + } + + /// <summary> + /// Gets the display preferences. + /// </summary> + /// <param name="userId">The user id.</param> + /// <param name="userDataId">The user data id.</param> + /// <returns>Task{DisplayPreferences}.</returns> + public Task<UserItemData> GetUserData(Guid userId, Guid userDataId) { - item.AddOrUpdateUserData(user, data); + var key = userId + userDataId.ToString(); - return Kernel.UserDataRepository.SaveUserData(item, CancellationToken.None); + return _userData.GetOrAdd(key, keyName => RetrieveUserData(userId, userDataId)); } + /// <summary> + /// Retrieves the display preferences. + /// </summary> + /// <param name="userId">The user id.</param> + /// <param name="userDataId">The user data id.</param> + /// <returns>DisplayPreferences.</returns> + private async Task<UserItemData> RetrieveUserData(Guid userId, Guid userDataId) + { + var userdata = await Kernel.Instance.UserDataRepository.GetUserData(userId, userDataId).ConfigureAwait(false); + + return userdata ?? new UserItemData(); + } } } diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs index c37b6b4a47..905d5413a7 100644 --- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; using System; @@ -17,6 +18,12 @@ namespace MediaBrowser.Server.Implementations.Sorting public User User { get; set; } /// <summary> + /// Gets or sets the user manager. + /// </summary> + /// <value>The user manager.</value> + public IUserManager UserManager { get; set; } + + /// <summary> /// Compares the specified x. /// </summary> /// <param name="x">The x.</param> @@ -34,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// <returns>DateTime.</returns> private DateTime GetDate(BaseItem x) { - var userdata = x.GetUserData(User, false); + var userdata = UserManager.GetUserData(User.Id, x.UserDataId).Result; if (userdata != null && userdata.LastPlayedDate.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs index 9cd5281c36..82e76e78d4 100644 --- a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -33,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// <returns>DateTime.</returns> private int GetValue(BaseItem x) { - var userdata = x.GetUserData(User, false); + var userdata = UserManager.GetUserData(User.Id, x.UserDataId).Result; return userdata == null ? 0 : userdata.PlayCount; } @@ -46,5 +47,11 @@ namespace MediaBrowser.Server.Implementations.Sorting { get { return ItemSortBy.PlayCount; } } + + /// <summary> + /// Gets or sets the user manager. + /// </summary> + /// <value>The user manager.</value> + public IUserManager UserManager { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs index baa38cde0c..44674e125c 100644 --- a/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs @@ -1,11 +1,9 @@ using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; -using System.Collections.Generic; using System.Data; using System.IO; using System.Threading; @@ -80,8 +78,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite string[] queries = { - "create table if not exists display_prefs (item_id GUID, user_id GUID, data BLOB)", - "create unique index if not exists idx_display_prefs on display_prefs (item_id, user_id)", + "create table if not exists displaypreferences (id GUID, userId GUID, data BLOB)", + "create unique index if not exists displaypreferencesindex on displaypreferences (id, userId)", "create table if not exists schema_version (table_name primary key, version)", //pragmas "pragma temp_store = memory" @@ -93,82 +91,87 @@ namespace MediaBrowser.Server.Implementations.Sqlite /// <summary> /// Save the display preferences associated with an item in the repo /// </summary> - /// <param name="item">The item.</param> + /// <param name="userId">The user id.</param> + /// <param name="displayPreferencesId">The display preferences id.</param> + /// <param name="displayPreferences">The display preferences.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException">item</exception> - public Task SaveDisplayPreferences(Folder item, CancellationToken cancellationToken) + public Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences, CancellationToken cancellationToken) { - if (item == null) + if (displayPreferences == null) { - throw new ArgumentNullException("item"); + throw new ArgumentNullException("displayPreferences"); } - if (cancellationToken == null) { throw new ArgumentNullException("cancellationToken"); } + if (userId == Guid.Empty) + { + throw new ArgumentNullException("userId"); + } + if (displayPreferencesId == Guid.Empty) + { + throw new ArgumentNullException("displayPreferencesId"); + } cancellationToken.ThrowIfCancellationRequested(); - + return Task.Run(() => { - var cmd = connection.CreateCommand(); + var serialized = _protobufSerializer.SerializeToBytes(displayPreferences); - cmd.CommandText = "delete from display_prefs where item_id = @guid"; - cmd.AddParam("@guid", item.DisplayPreferencesId); + cancellationToken.ThrowIfCancellationRequested(); + var cmd = connection.CreateCommand(); + cmd.CommandText = "replace into displaypreferences (id, userId, data) values (@1, @2, @3)"; + cmd.AddParam("@1", displayPreferencesId); + cmd.AddParam("@2", userId); + cmd.AddParam("@3", serialized); QueueCommand(cmd); - - if (item.DisplayPreferences != null) - { - foreach (var data in item.DisplayPreferences) - { - cmd = connection.CreateCommand(); - cmd.CommandText = "insert into display_prefs (item_id, user_id, data) values (@1, @2, @3)"; - cmd.AddParam("@1", item.DisplayPreferencesId); - cmd.AddParam("@2", data.UserId); - - cmd.AddParam("@3", _protobufSerializer.SerializeToBytes(data)); - - QueueCommand(cmd); - } - } }); } /// <summary> - /// Gets display preferences for an item + /// Gets the display preferences. /// </summary> - /// <param name="item">The item.</param> - /// <returns>IEnumerable{DisplayPreferences}.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public IEnumerable<DisplayPreferences> RetrieveDisplayPreferences(Folder item) + /// <param name="userId">The user id.</param> + /// <param name="displayPreferencesId">The display preferences id.</param> + /// <returns>Task{DisplayPreferences}.</returns> + /// <exception cref="System.ArgumentNullException">item</exception> + public async Task<DisplayPreferences> GetDisplayPreferences(Guid userId, Guid displayPreferencesId) { - if (item == null) + if (userId == Guid.Empty) + { + throw new ArgumentNullException("userId"); + } + if (displayPreferencesId == Guid.Empty) { - throw new ArgumentNullException("item"); + throw new ArgumentNullException("displayPreferencesId"); } var cmd = connection.CreateCommand(); - cmd.CommandText = "select data from display_prefs where item_id = @guid"; - var guidParam = cmd.Parameters.Add("@guid", DbType.Guid); - guidParam.Value = item.DisplayPreferencesId; + cmd.CommandText = "select data from displaypreferences where id = @id and userId=@userId"; + + var idParam = cmd.Parameters.Add("@id", DbType.Guid); + idParam.Value = displayPreferencesId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + var userIdParam = cmd.Parameters.Add("@userId", DbType.Guid); + userIdParam.Value = userId; + + using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow).ConfigureAwait(false)) { - while (reader.Read()) + if (reader.Read()) { using (var stream = GetStream(reader, 0)) { - var data = _protobufSerializer.DeserializeFromStream<DisplayPreferences>(stream); - if (data != null) - { - yield return data; - } + return _protobufSerializer.DeserializeFromStream<DisplayPreferences>(stream); } } } + + return null; } } } diff --git a/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs index dafdce798f..f3dede889d 100644 --- a/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs @@ -79,8 +79,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite string[] queries = { - "create table if not exists user_data (item_id GUID, user_id GUID, data BLOB)", - "create unique index if not exists idx_user_data on user_data (item_id, user_id)", + "create table if not exists userdata (id GUID, userId GUID, data BLOB)", + "create unique index if not exists userdataindex on userdata (id, userId)", "create table if not exists schema_version (table_name primary key, version)", //pragmas "pragma temp_store = memory" @@ -90,84 +90,101 @@ namespace MediaBrowser.Server.Implementations.Sqlite } /// <summary> - /// Save the user specific data associated with an item in the repo + /// Saves the user data. /// </summary> - /// <param name="item">The item.</param> + /// <param name="userId">The user id.</param> + /// <param name="userDataId">The user data id.</param> + /// <param name="userData">The user data.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public Task SaveUserData(BaseItem item, CancellationToken cancellationToken) + /// <exception cref="System.ArgumentNullException"> + /// userData + /// or + /// cancellationToken + /// or + /// userId + /// or + /// userDataId + /// </exception> + public Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken) { - if (item == null) + if (userData == null) { - throw new ArgumentNullException("item"); + throw new ArgumentNullException("userData"); } - if (cancellationToken == null) { throw new ArgumentNullException("cancellationToken"); } - + if (userId == Guid.Empty) + { + throw new ArgumentNullException("userId"); + } + if (userDataId == Guid.Empty) + { + throw new ArgumentNullException("userDataId"); + } + + cancellationToken.ThrowIfCancellationRequested(); + return Task.Run(() => { + var serialized = _protobufSerializer.SerializeToBytes(userData); + cancellationToken.ThrowIfCancellationRequested(); var cmd = connection.CreateCommand(); - - cmd.CommandText = "delete from user_data where item_id = @guid"; - cmd.AddParam("@guid", item.UserDataId); - + cmd.CommandText = "replace into userdata (id, userId, data) values (@1, @2, @3)"; + cmd.AddParam("@1", userDataId); + cmd.AddParam("@2", userId); + cmd.AddParam("@3", serialized); QueueCommand(cmd); - - if (item.UserData != null) - { - foreach (var data in item.UserData) - { - cmd = connection.CreateCommand(); - cmd.CommandText = "insert into user_data (item_id, user_id, data) values (@1, @2, @3)"; - cmd.AddParam("@1", item.UserDataId); - cmd.AddParam("@2", data.UserId); - - cmd.AddParam("@3", _protobufSerializer.SerializeToBytes(data)); - - QueueCommand(cmd); - } - } }); } /// <summary> - /// Gets user data for an item + /// Gets the user data. /// </summary> - /// <param name="item">The item.</param> - /// <returns>IEnumerable{UserItemData}.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public IEnumerable<UserItemData> RetrieveUserData(BaseItem item) + /// <param name="userId">The user id.</param> + /// <param name="userDataId">The user data id.</param> + /// <returns>Task{UserItemData}.</returns> + /// <exception cref="System.ArgumentNullException"> + /// userId + /// or + /// userDataId + /// </exception> + public async Task<UserItemData> GetUserData(Guid userId, Guid userDataId) { - if (item == null) + if (userId == Guid.Empty) { - throw new ArgumentNullException("item"); + throw new ArgumentNullException("userId"); + } + if (userDataId == Guid.Empty) + { + throw new ArgumentNullException("userDataId"); } var cmd = connection.CreateCommand(); - cmd.CommandText = "select data from user_data where item_id = @guid"; - var guidParam = cmd.Parameters.Add("@guid", DbType.Guid); - guidParam.Value = item.UserDataId; + cmd.CommandText = "select data from userdata where id = @id and userId=@userId"; + + var idParam = cmd.Parameters.Add("@id", DbType.Guid); + idParam.Value = userDataId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + var userIdParam = cmd.Parameters.Add("@userId", DbType.Guid); + userIdParam.Value = userId; + + using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow).ConfigureAwait(false)) { - while (reader.Read()) + if (reader.Read()) { using (var stream = GetStream(reader, 0)) { - var data = _protobufSerializer.DeserializeFromStream<UserItemData>(stream); - if (data != null) - { - yield return data; - } + return _protobufSerializer.DeserializeFromStream<UserItemData>(stream); } } } + + return null; } } } |
