/// <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 users = new List <User>(); // 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.Users .Where(item => batchIds.Contains(item.Id)); // Check if there were no items found. if (items == null || !items.Any()) { // Continue. continue; } // Get the items found. users = items .ToList(); } // Get the IDs of the items. var userIds = users .Select(item => item.Id); // Define the dependent list of items to get. var analysisInputs = new List <AnalysisInputModel>(); var networkInputs = new List <NetworkInputModel>(); // Use a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Get the items found. var networks = context.Networks .Where(item => item.NetworkUsers.All(item1 => userIds.Contains(item1.User.Id))) .Select(item => item.NetworkEdges) .SelectMany(item => item) .Select(item => item.Network) .Distinct(); // Get the IDs of the dependent items. analysisInputs = context.Analyses .Where(item => item.AnalysisUsers.All(item1 => userIds.Contains(item1.User.Id)) || item.AnalysisNetworks.Any(item1 => networks.Contains(item1.Network))) .Select(item => item.AnalysisEdges) .SelectMany(item => item) .Select(item => item.Analysis) .Distinct() .Select(item => new AnalysisInputModel { Id = item.Id }) .ToList(); networkInputs = networks .Select(item => new NetworkInputModel { Id = item.Id }) .ToList(); } // Delete the dependent entities. await new AnalysesTask { Items = analysisInputs }.DeleteAsync(serviceProvider, token); await new NetworksTask { Items = networkInputs }.DeleteAsync(serviceProvider, token); // Delete the related entities. await UserExtensions.DeleteRelatedEntitiesAsync <AnalysisUser>(userIds, serviceProvider, token); await UserExtensions.DeleteRelatedEntitiesAsync <NetworkUser>(userIds, serviceProvider, token); await UserExtensions.DeleteRelatedEntitiesAsync <DatabaseUser>(userIds, serviceProvider, token); // Define a variable to store the error messages. var errorMessages = new List <string>(); // Use a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new user manager instance. var userManager = scope.ServiceProvider.GetRequiredService <UserManager <User> >(); // Go over each item. foreach (var user in users) { // Delete it. var result = await userManager.DeleteAsync(user); // Check if the operation has failed. if (!result.Succeeded) { // Define the exception messages. var messages = result.Errors .Select(item => item.Description); // Add the exception messages to the error messages. errorMessages.AddRange(messages); } } } // Check if there have been any error messages. if (errorMessages.Any()) { // Throw an exception. throw new TaskException(string.Join(" ", errorMessages)); } } }