/// <summary> /// Generates a dictionary of all album IDs in the gallery and, for each one, a flattened list of all album IDs contained in it, /// recursively including all child IDs, not just those of its immediate children. The key is the album ID and the value is a list /// of all child album IDs contained in the album. /// </summary> /// <param name="albumRelationships">The album relationships for the current gallery.</param> /// <returns>ConcurrentDictionary<System.Int32, List<System.Int32>>.</returns> private static ConcurrentDictionary <int, List <int> > GenerateFlattenedAlbums(AlbumTuple[] albumRelationships) { var flatIds = new ConcurrentDictionary <int, List <int> >(); var albumLookup = albumRelationships.ToLookup(a => a.AlbumParentId, v => v); int?rootAlbumParentId = null; // Get a reference to the root album AlbumTuple rootAlbum = albumLookup[rootAlbumParentId].FirstOrDefault(); if (rootAlbum != null) { // Add the root album to our flat list and set up the child list flatIds.TryAdd(rootAlbum.AlbumId, new List <int> { rootAlbum.AlbumId }); // Now add the children of the root album foreach (AlbumTuple albumTuple in albumLookup[rootAlbum.AlbumId]) { FlattenAlbum(albumTuple, albumLookup, flatIds, new List <int> { rootAlbum.AlbumId }); } } return(flatIds); }
/// <summary> /// Flatten the gallery into a dictionary of album IDs (key) and the flattened list of all albums each album /// contains (value). /// </summary> /// <param name="galleryId">The gallery ID.</param> /// <returns>An instance of Dictionary<int, List<int>>.</returns> private static Dictionary <int, List <int> > FlattenGallery(int galleryId) { Dictionary <int, List <int> > flatIds = new Dictionary <int, List <int> >(); List <AlbumTuple> rawAlbums = new List <AlbumTuple>(); using (IDataReader dr = Album.GetCommandAlbumSelectAll(galleryId).ExecuteReader(CommandBehavior.CloseConnection)) { while (dr.Read()) { // SQL: //SELECT AlbumId, AlbumParentId //FROM dbo.[gs_Album] //WHERE FKGalleryId = @GalleryId rawAlbums.Add(new AlbumTuple { AlbumId = dr.GetInt32(0), AlbumParentId = dr.GetInt32(1) }); } } // To get the ILookup, we have to call ToLookup() on something that implements IEnumerable, so that's why // we converted the DataReader into a List of AlbumTuples first. ILookup <int, AlbumTuple> albums = rawAlbums.ToLookup(a => a.AlbumParentId, v => v); const int rootAlbumParentId = 0; // Get a reference to the root album AlbumTuple rootAlbum = albums[rootAlbumParentId].First(); // Add the root album to our flat list and set up the child list flatIds.Add(rootAlbum.AlbumId, new List <int> { rootAlbum.AlbumId }); // Now add the children of the root album foreach (AlbumTuple albumTuple in albums[rootAlbum.AlbumId]) { FlattenAlbum(albumTuple, albums, flatIds, new List <int> { rootAlbum.AlbumId }); } return(flatIds); }
/// <summary> /// Add the <paramref name="album" /> to all albums in <paramref name="flatIds" /> where it is a child. Recursively /// process the album's children. The end result is a dictionary of album IDs (key) and the flattened list of all albums /// each album contains (value). /// </summary> /// <param name="album">The album to flatten. This object is not modified.</param> /// <param name="hierarchicalIds">A lookup list where all albums (value) with a particular parent ID (key) can be quickly /// found. This object is not modified.</param> /// <param name="flatIds">The flattened list of albums and their child albums. The <paramref name="album" /> and its /// children are added to this list.</param> /// <param name="currentAlbumFlatIds">The current hierarchy of album IDs we are processing. The function uses this to /// know which items in <paramref name="flatIds" /> to update for each album.</param> private static void FlattenAlbum(AlbumTuple album, ILookup <int?, AlbumTuple> hierarchicalIds, ConcurrentDictionary <int, List <int> > flatIds, List <int> currentAlbumFlatIds) { // First time we get here, ID=2, ParentId=1 flatIds.TryAdd(album.AlbumId, new List <int> { album.AlbumId }); // For each album in the current hierarchy, find its match in flatIds and add the album to its list. foreach (int currentAlbumFlatId in currentAlbumFlatIds) { flatIds[currentAlbumFlatId].Add(album.AlbumId); } // Now add this album to the list so it will get updated when any children are processed. currentAlbumFlatIds.Add(album.AlbumId); foreach (AlbumTuple albumTuple in hierarchicalIds[album.AlbumId]) { FlattenAlbum(albumTuple, hierarchicalIds, flatIds, new List <int>(currentAlbumFlatIds)); } }
/// <summary> /// Add the <paramref name="album" /> to all albums in <paramref name="flatIds" /> where it is a child. Recursively /// process the album's children. The end result is a dictionary of album IDs (key) and the flattened list of all albums /// each album contains (value). /// </summary> /// <param name="album">The album to flatten. This object is not modified.</param> /// <param name="hierarchicalIds">A lookup list where all albums (value) with a particular parent ID (key) can be quickly /// found. This object is not modified.</param> /// <param name="flatIds">The flattened list of albums and their child albums. The <paramref name="album" /> and its /// children are added to this list.</param> /// <param name="currentAlbumFlatIds">The current hierarchy of album IDs we are processing. The function uses this to /// know which items in <paramref name="flatIds" /> to update for each album.</param> private static void FlattenAlbum(AlbumTuple album, ILookup<int, AlbumTuple> hierarchicalIds, Dictionary<int, List<int>> flatIds, List<int> currentAlbumFlatIds) { // First time we get here, ID=2, ParentId=1 flatIds.Add(album.AlbumId, new List<int> { album.AlbumId }); // For each album in the current hierarchy, find its match in flatIds and add the album to its list. foreach (int currentAlbumFlatId in currentAlbumFlatIds) { flatIds[currentAlbumFlatId].Add(album.AlbumId); } // Now add this album to the list so it will get updated when any children are processed. currentAlbumFlatIds.Add(album.AlbumId); foreach (AlbumTuple albumTuple in hierarchicalIds[album.AlbumId]) { FlattenAlbum(albumTuple, hierarchicalIds, flatIds, new List<int>(currentAlbumFlatIds)); } }