/// <summary>
        /// Edits the items in the database.
        /// </summary>
        /// <param name="serviceProvider">The application service provider.</param>
        /// <param name="token">The cancellation token for the task.</param>
        public async Task EditAsync(IServiceProvider serviceProvider, CancellationToken token)
        {
            // Check if there weren't any valid items found.
            if (Items == null)
            {
                // Throw an exception.
                throw new TaskException("No valid items could be found with the provided data.");
            }
            // Check if the exception item should be shown.
            var showExceptionItem = Items.Count() > 1;
            // Get the total number of batches.
            var count = Math.Ceiling((double)Items.Count() / ApplicationDbContext.BatchSize);

            // Go over each batch.
            for (var index = 0; index < count; index++)
            {
                // Check if the cancellation was requested.
                if (token.IsCancellationRequested)
                {
                    // Break.
                    break;
                }
                // Get the items in the current batch.
                var batchItems = Items
                                 .Skip(index * ApplicationDbContext.BatchSize)
                                 .Take(ApplicationDbContext.BatchSize);
                // Get the IDs of the items in the current batch.
                var batchIds = batchItems
                               .Where(item => !string.IsNullOrEmpty(item.Id))
                               .Select(item => item.Id);
                // Get the IDs of the related entities that appear in the current batch.
                var batchDatabaseIds = batchItems
                                       .Where(item => item.NodeCollectionDatabases != null)
                                       .Select(item => item.NodeCollectionDatabases)
                                       .SelectMany(item => item)
                                       .Where(item => item.Database != null)
                                       .Select(item => item.Database)
                                       .Where(item => !string.IsNullOrEmpty(item.Id))
                                       .Select(item => item.Id)
                                       .Distinct();
                var batchNodeIds = batchItems
                                   .Where(item => item.NodeCollectionNodes != null)
                                   .Select(item => item.NodeCollectionNodes)
                                   .SelectMany(item => item)
                                   .Where(item => item.Node != null)
                                   .Select(item => item.Node)
                                   .Where(item => !string.IsNullOrEmpty(item.Id))
                                   .Select(item => item.Id)
                                   .Distinct();
                // Define the list of items to get.
                var nodeCollections = new List <NodeCollection>();
                var databases       = new List <Database>();
                var nodes           = new List <Node>();
                // Use a new scope.
                using (var scope = serviceProvider.CreateScope())
                {
                    // Use a new context instance.
                    using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>();
                    // Get the items with the provided IDs.
                    var items = context.NodeCollections
                                .Where(item => !item.NodeCollectionDatabases.Any(item1 => item1.Database.DatabaseType.Name == "Generic"))
                                .Where(item => batchIds.Contains(item.Id));
                    // Check if there were no items found.
                    if (items == null || !items.Any())
                    {
                        // Continue.
                        continue;
                    }
                    // Get the items found.
                    nodeCollections = items
                                      .ToList();
                    // Get the related entities that appear in the current batch.
                    databases = context.Databases
                                .Where(item => item.DatabaseType.Name != "Generic")
                                .Where(item => batchDatabaseIds.Contains(item.Id))
                                .Distinct()
                                .ToList();
                    nodes = context.Nodes
                            .Where(item => !item.DatabaseNodes.Any(item1 => item1.Database.DatabaseType.Name == "Generic"))
                            .Where(item => batchNodeIds.Contains(item.Id))
                            .ToList();
                }
                // Get the IDs of the items.
                var nodeCollectionIds = nodeCollections
                                        .Select(item => item.Id);
                // Save the items to edit.
                var nodeCollectionsToEdit = new List <NodeCollection>();
                // Go over each of the valid items.
                foreach (var batchItem in batchItems)
                {
                    // Get the corresponding item.
                    var nodeCollection = nodeCollections
                                         .FirstOrDefault(item => batchItem.Id == item.Id);
                    // Check if there was no item found.
                    if (nodeCollection == null)
                    {
                        // Continue.
                        continue;
                    }
                    // Check if there were no node collection databases provided.
                    if (batchItem.NodeCollectionDatabases == null || !batchItem.NodeCollectionDatabases.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no node collection databases provided.", showExceptionItem, batchItem);
                    }
                    // Get the node collection databases.
                    var nodeCollectionDatabases = batchItem.NodeCollectionDatabases
                                                  .Where(item => item.Database != null)
                                                  .Where(item => !string.IsNullOrEmpty(item.Database.Id))
                                                  .Select(item => item.Database.Id)
                                                  .Distinct()
                                                  .Where(item => databases.Any(item1 => item1.Id == item))
                                                  .Select(item => new NodeCollectionDatabase
                    {
                        DatabaseId = item
                    });
                    // Check if there were no node collection databases found.
                    if (nodeCollectionDatabases == null || !nodeCollectionDatabases.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no node collection databases found.", showExceptionItem, batchItem);
                    }
                    // Check if there were no node collection nodes provided.
                    if (batchItem.NodeCollectionNodes == null || !batchItem.NodeCollectionNodes.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no node collection nodes provided.", showExceptionItem, batchItem);
                    }
                    // Get the node collection nodes.
                    var nodeCollectionNodes = batchItem.NodeCollectionNodes
                                              .Where(item => item.Node != null)
                                              .Where(item => !string.IsNullOrEmpty(item.Node.Id))
                                              .Where(item => nodes.Any(item1 => item1.Id == item.Node.Id))
                                              .Select(item => new NodeCollectionNode
                    {
                        NodeId = item.Node.Id
                    });
                    // Check if there were no node collection nodes found.
                    if (nodeCollectionNodes == null || !nodeCollectionNodes.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no node collection nodes found.", showExceptionItem, batchItem);
                    }
                    // Check if there were no node collection types provided.
                    if (batchItem.NodeCollectionTypes == null || !batchItem.NodeCollectionTypes.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no node collection types provided.", showExceptionItem, batchItem);
                    }
                    // Get the node collection types.
                    var nodeCollectionTypes = batchItem.NodeCollectionTypes
                                              .Select(item => item.Type)
                                              .Select(item => (Enum.TryParse <EnumerationNodeCollectionType>(item, out var type), type))
                                              .Where(item => item.Item1)
                                              .Select(item => new NodeCollectionType
                    {
                        Type = item.Item2
                    });
                    // Check if there were no node collection types found.
                    if (nodeCollectionTypes == null || !nodeCollectionTypes.Any())
                    {
                        // Throw an exception.
                        throw new TaskException("There were no node collection types found.", showExceptionItem, batchItem);
                    }
                    // Update the node collection.
                    nodeCollection.Name                    = batchItem.Name;
                    nodeCollection.Description             = batchItem.Description;
                    nodeCollection.NodeCollectionTypes     = nodeCollectionTypes.ToList();
                    nodeCollection.NodeCollectionDatabases = nodeCollectionDatabases.ToList();
                    nodeCollection.NodeCollectionNodes     = nodeCollectionNodes.ToList();
                    // Add the node collection to the list.
                    nodeCollectionsToEdit.Add(nodeCollection);
                }
                // Delete the dependent entities.
                await NodeCollectionExtensions.DeleteDependentAnalysesAsync(nodeCollectionIds, serviceProvider, token);

                await NodeCollectionExtensions.DeleteDependentNetworksAsync(nodeCollectionIds, serviceProvider, token);

                // Delete the related entities.
                await NodeCollectionExtensions.DeleteRelatedEntitiesAsync <NodeCollectionType>(nodeCollectionIds, serviceProvider, token);

                await NodeCollectionExtensions.DeleteRelatedEntitiesAsync <NodeCollectionNode>(nodeCollectionIds, serviceProvider, token);

                await NodeCollectionExtensions.DeleteRelatedEntitiesAsync <NodeCollectionDatabase>(nodeCollectionIds, serviceProvider, token);

                // Update the items.
                await IEnumerableExtensions.EditAsync(nodeCollectionsToEdit, serviceProvider, token);
            }
        }
        /// <summary>
        /// Deletes the items from the database.
        /// </summary>
        /// <param name="serviceProvider">The application service provider.</param>
        /// <param name="token">The cancellation token for the task.</param>
        public async Task DeleteAsync(IServiceProvider serviceProvider, CancellationToken token)
        {
            // Check if there weren't any valid items found.
            if (Items == null)
            {
                // Throw an exception.
                throw new TaskException("No valid items could be found with the provided data.");
            }
            // Get the total number of batches.
            var count = Math.Ceiling((double)Items.Count() / ApplicationDbContext.BatchSize);

            // Go over each batch.
            for (var index = 0; index < count; index++)
            {
                // Check if the cancellation was requested.
                if (token.IsCancellationRequested)
                {
                    // Break.
                    break;
                }
                // Get the items in the current batch.
                var batchItems = Items
                                 .Skip(index * ApplicationDbContext.BatchSize)
                                 .Take(ApplicationDbContext.BatchSize);
                // Get the IDs of the items in the current batch.
                var batchIds = batchItems.Select(item => item.Id);
                // Define the list of items to get.
                var nodeCollections = new List <NodeCollection>();
                // Use a new scope.
                using (var scope = serviceProvider.CreateScope())
                {
                    // Use a new context instance.
                    using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>();
                    // Get the items with the provided IDs.
                    var items = context.NodeCollections
                                .Where(item => batchIds.Contains(item.Id));
                    // Check if there were no items found.
                    if (items == null || !items.Any())
                    {
                        // Continue.
                        continue;
                    }
                    // Get the items found.
                    nodeCollections = items
                                      .ToList();
                }
                // Get the IDs of the items.
                var nodeCollectionIds = nodeCollections
                                        .Select(item => item.Id);
                // Delete the dependent entities.
                await NodeCollectionExtensions.DeleteDependentAnalysesAsync(nodeCollectionIds, serviceProvider, token);

                await NodeCollectionExtensions.DeleteDependentNetworksAsync(nodeCollectionIds, serviceProvider, token);

                // Delete the related entities.
                await NodeCollectionExtensions.DeleteRelatedEntitiesAsync <NodeCollectionType>(nodeCollectionIds, serviceProvider, token);

                await NodeCollectionExtensions.DeleteRelatedEntitiesAsync <NodeCollectionNode>(nodeCollectionIds, serviceProvider, token);

                await NodeCollectionExtensions.DeleteRelatedEntitiesAsync <NodeCollectionDatabase>(nodeCollectionIds, serviceProvider, token);

                // Delete the items.
                await IEnumerableExtensions.DeleteAsync(nodeCollections, serviceProvider, token);
            }
        }
        public async Task <IActionResult> OnPostAsync()
        {
            // Get the current user.
            var user = await _userManager.GetUserAsync(User);

            // Check if there aren't any IDs provided.
            if (Input.Ids == null || !Input.Ids.Any())
            {
                // Display a message.
                TempData["StatusMessage"] = "Error: No or invalid IDs have been provided.";
                // Redirect to the index page.
                return(RedirectToPage("/Content/DatabaseTypes/PPI/Data/NodeCollections/Index"));
            }
            // Define the view.
            View = new ViewModel
            {
                Items = _context.NodeCollections
                        .Where(item => item.NodeCollectionDatabases.Any(item1 => item1.Database.DatabaseType.Name == "PPI"))
                        .Where(item => item.NodeCollectionDatabases.Any(item1 => item1.Database.IsPublic || item1.Database.DatabaseUsers.Any(item2 => item2.User == user)))
                        .Where(item => Input.Ids.Contains(item.Id))
            };
            // Check if there weren't any items found.
            if (View.Items == null || !View.Items.Any())
            {
                // Display a message.
                TempData["StatusMessage"] = "Error: No items have been found with the provided IDs, or you don't have access to them.";
                // Redirect to the index page.
                return(RedirectToPage("/Content/DatabaseTypes/PPI/Data/NodeCollections/Index"));
            }
            // Check if the reCaptcha is valid.
            if (!await _reCaptchaChecker.IsValid(Input.ReCaptchaToken))
            {
                // Add an error to the model.
                ModelState.AddModelError(string.Empty, "The reCaptcha verification failed.");
                // Return the page.
                return(Page());
            }
            // Check if the provided model isn't valid.
            if (!ModelState.IsValid)
            {
                // Add an error to the model.
                ModelState.AddModelError(string.Empty, "An error has been encountered. Please check again the input fields.");
                // Redisplay the page.
                return(Page());
            }
            // Return the streamed file.
            return(new FileCallbackResult(MediaTypeNames.Application.Zip, async(zipStream, _) =>
            {
                // Define a new ZIP archive.
                using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create);
                // Check if the overview file should be added.
                if (true)
                {
                    // Create a new entry in the archive and open it.
                    using var stream = archive.CreateEntry($"Collections-List.txt", CompressionLevel.Fastest).Open();
                    // Write to the entry the corresponding file content.
                    await NodeCollectionExtensions.WriteToStreamOverviewTextFileContent(View.Items.Select(item => item.Id), stream, _serviceProvider, HttpContext.Request.Scheme, HttpContext.Request.Host);
                }
                // Check which should be the format of the files within the archive.
                if (Input.FileFormat == "txt")
                {
                    // Go over each of the node collections to download.
                    foreach (var nodeCollection in View.Items)
                    {
                        // Create a new entry in the archive and open it.
                        using var stream = archive.CreateEntry($"Collections-{nodeCollection.Name.Replace(" ", "-")}-{nodeCollection.Id}.txt", CompressionLevel.Fastest).Open();
                        // Write to the entry the corresponding file content.
                        await nodeCollection.WriteToStreamTxtFileContent(stream, _serviceProvider);
                    }
                }
                else if (Input.FileFormat == "json")
                {
                    // Go over each of the node collections to download.
                    foreach (var nodeCollection in View.Items)
                    {
                        // Create a new entry in the archive and open it.
                        using var stream = archive.CreateEntry($"Collections-{nodeCollection.Name.Replace(" ", "-")}-{nodeCollection.Id}.json", CompressionLevel.Fastest).Open();
                        // Write to the entry the corresponding file content.
                        await nodeCollection.WriteToStreamJsonFileContent(stream, _serviceProvider);
                    }
                }
                else if (Input.FileFormat == "xlsx")
                {
                    // Go over each of the node collections to download.
                    foreach (var nodeCollection in View.Items)
                    {
                        // Create a new entry in the archive and open it.
                        using var stream = archive.CreateEntry($"Collections-{nodeCollection.Name.Replace(" ", "-")}-{nodeCollection.Id}.xlsx", CompressionLevel.Fastest).Open();
                        // Write to the entry the corresponding file content.
                        await nodeCollection.WriteToStreamXlsxFileContent(stream, _serviceProvider);
                    }
                }
            })
            {
                FileDownloadName = $"NetControl4BioMed-Collections-{DateTime.UtcNow:yyyyMMdd}.zip"
            });