/// <summary> /// Updates the Genre in the Genres collection. /// </summary> /// <param name="UnitOfWork">The In-Memory context</param> /// <param name="Genre">The Genre to be updated</param> /// <param name="Album">The album</param> /// <returns>The Updated Genre</returns> /// <remarks> /// <para> /// The update genre is returned so that it can replace the /// genre in the album, which means the navigation properties /// are up to date. /// </para> /// <para> /// Only add an AlbumId if to the AlbumIds collection if it's not already there. /// It won't be if the its is a New Album being created, but there will be when /// reloading the persisted data. /// </para> /// <para> /// Concurrency: /// </para> /// <Para> /// This routine provides a Monitor lock to ensure that only one instance of this /// can modify the Genres collection at a time. /// It locks from the point where the Genre to be updated is retrieved from /// the Genres /// and retains that until the Genre is updated in the Genres collection. /// This type of lock is preferred to ensure that no other updates to the Genres /// is attempted while this update occurs. /// </Para> /// <para> /// This is a very course grained way of locking but is acceptible within this /// application as it is a Windows 8 store app, and not subjected to multiple /// users, only the individual threads within the application. The performance /// hit should not be that noticable here. /// </para> /// </remarks> private Genre UpdateGenre(IUnitOfWork UnitOfWork, Genre Genre, Album Album) { // TODO: Refactor this to use the concurrent collection. var idx = 0; lock (_GenreLock) { // Get the index of the Genre idx = UnitOfWork.Genres.FindIndex(g => g.Name == Genre.Name); // Get the Genre var updatedGenre = UnitOfWork.Genres[idx]; // If Album exists in the retrieved Genre. var al = updatedGenre.Albums.FirstOrDefault(a => a.Id == Album.Id); if (al != null) { // The Album is found, so replace it var alIdx = updatedGenre.Albums.IndexOf(al); updatedGenre.Albums[alIdx] = Album; } else { // Track dosn't exist in the Genres.Tracks collection, so just add it. AddAlbumToGenre(updatedGenre, Album); } // Replace the Genre in the Genres collection UnitOfWork.Genres[idx] = updatedGenre; } // return the updated Genre return UnitOfWork.Genres[idx]; }
/// <summary> /// Adds the Album and, if necessary, the Album Id to the Genre /// </summary> /// <param name="Genre">The Genre being updated</param> /// <param name="Album">The album updating the Genre</param> /// <remarks> /// <para> /// Only add an AlbumId if to the AlbumIds collection if it's not already there. /// It won't be if the its is a New Album being created, but there will be when /// reloading the persisted data. /// </para> /// <para> /// Concurrency /// </para> /// <para> /// This method doesn't need to be locked as it can only be called from either /// AddGenre or Updategenre methods, and these are both locking. /// </para> /// </remarks> private void AddAlbumToGenre(Genre Genre, Album Album) { // Add the Album to the albums collection Genre.Albums.Add(Album); // Only add an AlbumId if to the AlbumIds collection if it's not already there. // It won't be if the its is a New Album being created, // but there will be when reloading the persisted data. if (!Genre.AlbumIds.Contains(Album.Id)) Genre.AlbumIds.Add(Album.Id); }
/// <summary> /// Adds a new Genre to the Genres collection of the Domain model. It /// returns an instance of the Genre added so that it can be used elsewhere. /// This is standard coding for creating a new object. /// </summary> /// <param name="UnitOfWork">The In-Memory context</param> /// <param name="Genre">the new Genre</param> /// <param name="Album">The album the Genre relates to</param> /// <returns>The updated instance of the new Genre</returns> /// <remarks> /// Only add an AlbumId if to the AlbumIds collection if it's not already there. /// It won't be if the its is a New Album being created, but there will be when /// reloading the persisted data. /// <para> /// Concurrency: /// </para> /// <Para> /// This routine provides a Monitor lock to ensure that only one instance of this /// can modify the Genres collection at a time. /// It locks from the point which a new Id is generated for the Genre being added /// and retains that until the Genre is added to the Genres collection. /// This type of lock is preferred to ensure the generated Id is updated within /// the Genres collection before any other thread can try and Add a Genre which /// would require the Id for this one, which woudl be used in the GenerateId /// methods. This is to avoid duplicate Id's being generated. /// </Para> /// <para> /// This is a very course grained way of locking but is acceptible within this /// application as it is a Windows 8 store app, and not subjected to multiple /// users, only the individual threads within the application. The performance /// hit should not be that noticable here. /// </para> /// </remarks> private Genre AddGenre(IUnitOfWork UnitOfWork, Genre Genre, Album Album) { lock (_GenreLock) { Genre.Albums = new List<Album>(); // Concurrency: Lock between getting the Id and performing the update, as the // this new Id won't be availble for checking purposes by another // thread that is looking to add a Genre. This should avoid the // possiblilties of duplicate Id's // i. Generate GenreId, if there isn't one, will be if reloading persisted data. if (Genre.Id == 0) Genre.Id = GenerateGenreId(UnitOfWork); // ii. Add album ref to Genre AddAlbumToGenre(Genre, Album); // iii.Add Genre to Genres Collection UnitOfWork.Genres.Add(Genre); } return Genre; }