/// <summary> /// Creates 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 CreateAsync(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); // Check if any of the IDs are repeating in the list. if (batchIds.Distinct().Count() != batchIds.Count()) { // Throw an exception. throw new TaskException("Two or more of the manually provided IDs are duplicated."); } // 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 validBatchIds = new List <string>(); 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 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 valid IDs, that do not appear in the database. validBatchIds = batchIds .Except(context.NodeCollections .Where(item => batchIds.Contains(item.Id)) .Select(item => item.Id)) .ToList(); } // Save the items to add. var nodeCollectionsToAdd = new List <NodeCollection>(); // Go over each of the items. foreach (var batchItem in batchItems) { // Check if the ID of the item is not valid. if (!string.IsNullOrEmpty(batchItem.Id) && !validBatchIds.Contains(batchItem.Id)) { // 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); } // Define the new node collection. var nodeCollection = new NodeCollection { DateTimeCreated = DateTime.UtcNow, Name = batchItem.Name, Description = batchItem.Description, NodeCollectionTypes = nodeCollectionTypes.ToList(), NodeCollectionDatabases = nodeCollectionDatabases.ToList(), NodeCollectionNodes = nodeCollectionNodes.ToList() }; // Check if there is any ID provided. if (!string.IsNullOrEmpty(batchItem.Id)) { // Assign it to the node collection. nodeCollection.Id = batchItem.Id; } // Add the new node collection to the list. nodeCollectionsToAdd.Add(nodeCollection); } // Create the items. await IEnumerableExtensions.CreateAsync(nodeCollectionsToAdd, serviceProvider, token); } }
/// <summary> /// Creates 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 CreateAsync(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 related entities that appear in the current batch. var batchAnalysisIds = batchItems .Where(item => item.Analysis != null) .Select(item => item.Analysis) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchUserIds = batchItems .Where(item => item.User != null) .Select(item => item.User) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); // Define the list of items to get. var analyses = new List <Analysis>(); var users = new List <User>(); // Create a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Get the related entities that appear in the current batch. analyses = context.Analyses .Where(item => batchAnalysisIds.Contains(item.Id)) .ToList(); users = context.Users .Where(item => batchUserIds.Contains(item.Id)) .ToList(); } // Save the items to add. var analysisUsersToAdd = new List <AnalysisUser>(); // Go over each item in the current batch. foreach (var batchItem in batchItems) { // Check if there was no analysis provided. if (batchItem.Analysis == null || string.IsNullOrEmpty(batchItem.Analysis.Id)) { // Throw an exception. throw new TaskException("There was no analysis provided.", showExceptionItem, batchItem); } // Get the analysis. var analysis = analyses .FirstOrDefault(item => item.Id == batchItem.Analysis.Id); // Check if there was no analysis found. if (analysis == null) { // Throw an exception. throw new TaskException($"There was no analysis found.", showExceptionItem, batchItem); } // Check if there was no user provided. if (batchItem.User == null || string.IsNullOrEmpty(batchItem.User.Id)) { // Throw an exception. throw new TaskException("There was no user provided.", showExceptionItem, batchItem); } // Get the user. var user = users .FirstOrDefault(item => item.Id == batchItem.User.Id); // Check if there was no user found. if (user == null) { // Throw an exception. throw new TaskException($"There was no user found.", showExceptionItem, batchItem); } // Define the new item. var analysisUser = new AnalysisUser { DateTimeCreated = DateTime.UtcNow, AnalysisId = analysis.Id, UserId = user.Id }; // Add the item to the list. analysisUsersToAdd.Add(analysisUser); } // Create the items. await IEnumerableExtensions.CreateAsync(analysisUsersToAdd, serviceProvider, token); } }
/// <summary> /// Creates 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 CreateAsync(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); var batchNames = batchItems .Where(item => !string.IsNullOrEmpty(item.Name)) .Select(item => item.Name) .Distinct(); // Check if any of the IDs are repeating in the list. if (batchIds.Distinct().Count() != batchIds.Count()) { // Throw an exception. throw new TaskException("Two or more of the manually provided IDs are duplicated."); } // Get the IDs of the related entities that appear in the current batch. var batchDatabaseIds = batchItems .Where(item => item.Database != null) .Select(item => item.Database) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); // Define the list of items to get. var databases = new List <Database>(); var existingDatabaseEdgeFieldNames = new List <string>(); var validBatchIds = new List <string>(); // Use a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Get the related entities that appear in the current batch. databases = context.Databases .Include(item => item.DatabaseType) .Where(item => batchDatabaseIds.Contains(item.Id)) .ToList(); existingDatabaseEdgeFieldNames = context.DatabaseEdgeFields .Where(item => batchNames.Contains(item.Name)) .Select(item => item.Name) .ToList(); // Get the valid IDs, that do not appear in the database. validBatchIds = batchIds .Except(context.DatabaseEdgeFields .Where(item => batchIds.Contains(item.Id)) .Select(item => item.Id)) .ToList(); } // Save the items to add. var databaseEdgeFieldsToAdd = new List <DatabaseEdgeField>(); // Go over each item in the current batch. foreach (var batchItem in batchItems) { // Check if the ID of the item is not valid. if (!string.IsNullOrEmpty(batchItem.Id) && !validBatchIds.Contains(batchItem.Id)) { // Continue. continue; } // Check if there is another database edge field with the same name. if (existingDatabaseEdgeFieldNames.Any(item => item == batchItem.Name) || databaseEdgeFieldsToAdd.Any(item => item.Name == batchItem.Name)) { // Throw an exception. throw new TaskException("A database edge field with the same name already exists.", showExceptionItem, batchItem); } // Check if there was no database provided. if (batchItem.Database == null || string.IsNullOrEmpty(batchItem.Database.Id)) { // Throw an exception. throw new TaskException("There was no database provided.", showExceptionItem, batchItem); } // Get the database. var database = databases .FirstOrDefault(item => item.Id == batchItem.Database.Id); // Check if there was no database found. if (database == null) { // Throw an exception. throw new TaskException("There was no database found.", showExceptionItem, batchItem); } // Check if the database is generic. if (database.DatabaseType.Name == "Generic") { // Throw an exception. throw new TaskException("The database edge field can't be generic.", showExceptionItem, batchItem); } // Define the new item. var databaseEdgeField = new DatabaseEdgeField { DateTimeCreated = DateTime.UtcNow, Name = batchItem.Name, Description = batchItem.Description, Url = batchItem.Url, IsSearchable = batchItem.IsSearchable, DatabaseId = database.Id }; // Check if there is any ID provided. if (!string.IsNullOrEmpty(batchItem.Id)) { // Assign it to the item. database.Id = batchItem.Id; } // Add the item to the list. databaseEdgeFieldsToAdd.Add(databaseEdgeField); } // Create the items. await IEnumerableExtensions.CreateAsync(databaseEdgeFieldsToAdd, serviceProvider, token); } }
/// <summary> /// Creates 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 CreateAsync(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 related entities that appear in the current batch. var batchNetworkIds = batchItems .Where(item => item.Network != null) .Select(item => item.Network) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchUserEmails = batchItems .Where(item => !string.IsNullOrEmpty(item.Email)) .Select(item => item.Email) .Distinct(); // Define the list of items to get. var networks = new List <Network>(); var users = new List <User>(); // Create a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Get the related entities that appear in the current batch. networks = context.Networks .Where(item => batchNetworkIds.Contains(item.Id)) .ToList(); users = context.Users .Where(item => batchUserEmails.Contains(item.Email)) .ToList(); } // Save the items to add. var networkUserInvitationsToAdd = new List <NetworkUserInvitation>(); // Go over each item in the current batch. foreach (var batchItem in batchItems) { // Check if there was no network provided. if (batchItem.Network == null || string.IsNullOrEmpty(batchItem.Network.Id)) { // Throw an exception. throw new TaskException("There was no network provided.", showExceptionItem, batchItem); } // Get the network. var network = networks .FirstOrDefault(item => item.Id == batchItem.Network.Id); // Check if there was no network found. if (network == null) { // Throw an exception. throw new TaskException("There was no network found.", showExceptionItem, batchItem); } // Check if there was no e-mail provided. if (string.IsNullOrEmpty(batchItem.Email)) { // Throw an exception. throw new TaskException("There was no e-mail provided.", showExceptionItem, batchItem); } // Try to get the user. var user = users .FirstOrDefault(item => item.Email == batchItem.Email); // Check if there was a user found. if (user != null) { // Throw an exception. throw new TaskException("The user with the provided e-mail already exists.", showExceptionItem, batchItem); } // Define the new item. var networkUserInvitation = new NetworkUserInvitation { DateTimeCreated = DateTime.UtcNow, NetworkId = network.Id, Email = batchItem.Email }; // Add the item to the list. networkUserInvitationsToAdd.Add(networkUserInvitation); } // Create the items. await IEnumerableExtensions.CreateAsync(networkUserInvitationsToAdd, serviceProvider, token); } }
/// <summary> /// Creates 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 CreateAsync(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); // Check if any of the IDs are repeating in the list. if (batchIds.Distinct().Count() != batchIds.Count()) { // Throw an exception. throw new TaskException("Two or more of the manually provided IDs are duplicated."); } // Get the IDs of the related entities that appear in the current batch. var batchDatabaseIds = batchItems .Where(item => item.DatabaseEdges != null) .Select(item => item.DatabaseEdges) .SelectMany(item => item) .Where(item => item.Database != null) .Select(item => item.Database) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchDatabaseEdgeFieldIds = batchItems .Where(item => item.DatabaseEdgeFieldEdges != null) .Select(item => item.DatabaseEdgeFieldEdges) .SelectMany(item => item) .Where(item => item.DatabaseEdgeField != null) .Select(item => item.DatabaseEdgeField) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchNodeIds = batchItems .Where(item => item.EdgeNodes != null) .Select(item => item.EdgeNodes) .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 validBatchIds = new List <string>(); var databaseEdgeFields = new List <DatabaseEdgeField>(); 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 related entities that appear in the current batch. databaseEdgeFields = context.DatabaseEdgeFields .Where(item => item.Database.DatabaseType.Name != "Generic") .Where(item => batchDatabaseEdgeFieldIds.Contains(item.Id)) .ToList(); databases = context.Databases .Where(item => item.DatabaseType.Name != "Generic") .Where(item => batchDatabaseIds.Contains(item.Id)) .Concat(context.DatabaseEdgeFields .Where(item => item.Database.DatabaseType.Name != "Generic") .Where(item => batchDatabaseEdgeFieldIds.Contains(item.Id)) .Select(item => item.Database)) .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 valid IDs, that do not appear in the database. validBatchIds = batchIds .Except(context.Edges .Where(item => batchIds.Contains(item.Id)) .Select(item => item.Id)) .ToList(); } // Save the items to add. var edgesToAdd = new List <Edge>(); // Go over each of the items. foreach (var batchItem in batchItems) { // Check if the ID of the item is not valid. if (!string.IsNullOrEmpty(batchItem.Id) && !validBatchIds.Contains(batchItem.Id)) { // Continue. continue; } // Check if there were no edge nodes provided. if (batchItem.EdgeNodes == null || !batchItem.EdgeNodes.Any()) { // Throw an exception. throw new TaskException("There were no edge nodes provided.", showExceptionItem, batchItem); } // Get the edge nodes. var edgeNodes = batchItem.EdgeNodes .Where(item => item.Node != null) .Where(item => !string.IsNullOrEmpty(item.Node.Id)) .Where(item => item.Type == "Source" || item.Type == "Target") .Select(item => (item.Node.Id, item.Type)) .Distinct() .Where(item => nodes.Any(item1 => item1.Id == item.Item1)) .Select(item => new EdgeNode { NodeId = item.Item1, Type = EnumerationExtensions.GetEnumerationValue <EdgeNodeType>(item.Item2) }); // Check if there were no edge nodes found. if (edgeNodes == null || !edgeNodes.Any(item => item.Type == EdgeNodeType.Source) || !edgeNodes.Any(item => item.Type == EdgeNodeType.Target)) { // Throw an exception. throw new TaskException("There were no edge nodes found.", showExceptionItem, batchItem); } // Check if there were no database edges or database edge field edges provided. if ((batchItem.DatabaseEdges == null || !batchItem.DatabaseEdges.Any()) && (batchItem.DatabaseEdgeFieldEdges == null || !batchItem.DatabaseEdgeFieldEdges.Any())) { // Throw an exception. throw new TaskException("There were no database edges or database edge field edges provided.", showExceptionItem, batchItem); } // Get the database edge field edges. var databaseEdgeFieldEdges = batchItem.DatabaseEdgeFieldEdges != null? batchItem.DatabaseEdgeFieldEdges .Where(item => item.DatabaseEdgeField != null) .Where(item => !string.IsNullOrEmpty(item.DatabaseEdgeField.Id)) .Where(item => !string.IsNullOrEmpty(item.Value)) .Select(item => (item.DatabaseEdgeField.Id, item.Value)) .Distinct() .Where(item => databaseEdgeFields.Any(item1 => item1.Id == item.Item1)) .Select(item => new DatabaseEdgeFieldEdge { DatabaseEdgeFieldId = item.Item1, Value = item.Item2 }) : Enumerable.Empty <DatabaseEdgeFieldEdge>(); // Get the database edges. var databaseEdgeFieldIds = databaseEdgeFieldEdges .Select(item => item.DatabaseEdgeFieldId) .Distinct(); var currentDatabaseEdgeFields = databaseEdgeFields .Where(item => databaseEdgeFieldIds.Contains(item.Id)); var databaseEdges = batchItem.DatabaseEdges != null? batchItem.DatabaseEdges .Where(item => item.Database != null) .Where(item => !string.IsNullOrEmpty(item.Database.Id)) .Select(item => item.Database.Id) .Concat(currentDatabaseEdgeFields .Select(item => item.Database.Id)) .Distinct() .Where(item => databases.Any(item1 => item1.Id == item)) .Select(item => new DatabaseEdge { DatabaseId = item, }) : Enumerable.Empty <DatabaseEdge>(); // Check if there were no database edges found. if (databaseEdges == null || !databaseEdges.Any()) { // Throw an exception. throw new TaskException("There were no database edges found.", showExceptionItem, batchItem); } // Define the new edge. var edge = new Edge { DateTimeCreated = DateTime.UtcNow, Name = string.Concat(nodes.First(item => item.Id == edgeNodes.First(item => item.Type == EdgeNodeType.Source).NodeId).Name, " - ", nodes.First(item => item.Id == edgeNodes.First(item => item.Type == EdgeNodeType.Target).NodeId).Name), Description = batchItem.Description, EdgeNodes = new List <EdgeNode> { edgeNodes.First(item => item.Type == EdgeNodeType.Source), edgeNodes.First(item => item.Type == EdgeNodeType.Target) }, DatabaseEdgeFieldEdges = databaseEdgeFieldEdges.ToList(), DatabaseEdges = databaseEdges.ToList() }; // Check if there is any ID provided. if (!string.IsNullOrEmpty(batchItem.Id)) { // Assign it to the node. edge.Id = batchItem.Id; } // Add the new node to the list. edgesToAdd.Add(edge); } // Create the items. await IEnumerableExtensions.CreateAsync(edgesToAdd, serviceProvider, token); } }
/// <summary> /// Creates 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 <IEnumerable <string> > CreateAsync(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); // Save the IDs of the created items. var ids = Enumerable.Empty <string>(); // 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); // Check if any of the IDs are repeating in the list. if (batchIds.Distinct().Count() != batchIds.Count()) { // Throw an exception. throw new TaskException("One or more of the manually provided IDs are duplicated."); } // Get the IDs of the related entities that appear in the current batch. var batchUserIds = batchItems .Where(item => item.NetworkUsers != null) .Select(item => item.NetworkUsers) .SelectMany(item => item) .Where(item => item.User != null) .Select(item => item.User) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchDatabaseIds = batchItems .Where(item => item.NetworkDatabases != null) .Select(item => item.NetworkDatabases) .SelectMany(item => item) .Where(item => item.Database != null) .Select(item => item.Database) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); var batchNodeCollectionIds = batchItems .Where(item => item.NetworkNodeCollections != null) .Select(item => item.NetworkNodeCollections) .SelectMany(item => item) .Where(item => item.NodeCollection != null) .Select(item => item.NodeCollection) .Where(item => !string.IsNullOrEmpty(item.Id)) .Select(item => item.Id) .Distinct(); // Define the list of items to get. var users = new List <User>(); var databases = new List <Database>(); var nodeCollections = new List <NodeCollection>(); var validBatchIds = new List <string>(); // Use a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Get the related entities that appear in the current batch. users = context.Users .Where(item => batchUserIds.Contains(item.Id)) .ToList(); databases = context.Databases .Include(item => item.DatabaseType) .Where(item => batchDatabaseIds.Contains(item.Id)) .ToList(); nodeCollections = context.NodeCollections .Include(item => item.NodeCollectionDatabases) .ThenInclude(item => item.Database) .Where(item => batchNodeCollectionIds.Contains(item.Id)) .ToList(); // Get the valid IDs, that do not appear in the database. validBatchIds = batchIds .Except(context.Networks .Where(item => batchIds.Contains(item.Id)) .Select(item => item.Id)) .ToList(); } // Save the items to add. var networksToAdd = new List <Network>(); // Go over each item in the current batch. foreach (var batchItem in batchItems) { // Check if the ID of the item is not valid. if (!string.IsNullOrEmpty(batchItem.Id) && !validBatchIds.Contains(batchItem.Id)) { // Continue. continue; } // Check if there are no network users provided. if (!batchItem.IsPublic && (batchItem.NetworkUsers == null || !batchItem.NetworkUsers.Any())) { // Throw an exception. throw new TaskException("There were no network users provided and the network is not public.", showExceptionItem, batchItem); } // Get the network users. var networkUsers = batchItem.NetworkUsers .Where(item => item.User != null) .Where(item => !string.IsNullOrEmpty(item.User.Id)) .Select(item => item.User.Id) .Distinct() .Where(item => users.Any(item1 => item1.Id == item)) .Select(item => new NetworkUser { DateTimeCreated = DateTime.UtcNow, UserId = item }); // Check if there were no network users found. if (!batchItem.IsPublic && (networkUsers == null || !networkUsers.Any())) { // Throw an exception. throw new TaskException("There were no network users found and the network is not public.", showExceptionItem, batchItem); } // Check if there are no network databases provided. if (batchItem.NetworkDatabases == null || !batchItem.NetworkDatabases.Any()) { // Throw an exception. throw new TaskException("There were no network databases provided.", showExceptionItem, batchItem); } // Get the network databases. var networkDatabases = batchItem.NetworkDatabases .Where(item => item.Database != null) .Where(item => !string.IsNullOrEmpty(item.Database.Id)) .Where(item => item.Type == "Node" || item.Type == "Edge") .Select(item => (item.Database.Id, item.Type)) .Distinct() .Where(item => databases.Any(item1 => item1.Id == item.Item1)) .Select(item => new NetworkDatabase { DatabaseId = item.Item1, Type = EnumerationExtensions.GetEnumerationValue <NetworkDatabaseType>(item.Item2) }); // Check if there were no network databases found. if (networkDatabases == null || !networkDatabases.Any()) { // Throw an exception. throw new TaskException("There were no network databases found.", showExceptionItem, batchItem); } // Check if the network databases have different database types. var batchNetworkDatabaseIds = networkDatabases.Select(item => item.DatabaseId); if (databases.Where(item => batchNetworkDatabaseIds.Contains(item.Id)).Select(item => item.DatabaseType).Distinct().Count() > 1) { // Throw an exception. throw new TaskException("The network databases found have different database types.", showExceptionItem, batchItem); } // Get the node database IDs. var nodeDatabaseIds = networkDatabases .Where(item => item.Type == NetworkDatabaseType.Node) .Select(item => item.DatabaseId); // Get the network node collections. var networkNodeCollections = batchItem.NetworkNodeCollections != null? batchItem.NetworkNodeCollections .Where(item => item.NodeCollection != null) .Where(item => !string.IsNullOrEmpty(item.NodeCollection.Id)) .Where(item => item.Type == "Seed") .Select(item => (item.NodeCollection.Id, item.Type)) .Distinct() .Where(item => nodeCollections.Any(item1 => item1.Id == item.Item1 && item1.NodeCollectionDatabases.Any(item2 => nodeDatabaseIds.Contains(item2.Database.Id)))) .Select(item => new NetworkNodeCollection { NodeCollectionId = item.Item1, Type = EnumerationExtensions.GetEnumerationValue <NetworkNodeCollectionType>(item.Item2) }) : Enumerable.Empty <NetworkNodeCollection>(); // Define the new item. var network = new Network { DateTimeCreated = DateTime.UtcNow, Name = batchItem.Name, Description = batchItem.Description, IsPublic = batchItem.IsPublic, Status = NetworkStatus.Defined, Log = JsonSerializer.Serialize(Enumerable.Empty <string>()), Data = batchItem.Data, NetworkDatabases = networkDatabases.ToList(), NetworkUsers = networkUsers.ToList(), NetworkNodeCollections = networkNodeCollections.ToList() }; // Try to get the algorithm. try { // Get the algorithm. network.Algorithm = EnumerationExtensions.GetEnumerationValue <NetworkAlgorithm>(batchItem.Algorithm); } catch (Exception exception) { // Get the exception message. var message = string.IsNullOrEmpty(exception.Message) ? string.Empty : " " + exception.Message; // Throw an exception. throw new TaskException("The algorithm couldn't be determined from the provided string." + message, showExceptionItem, batchItem); } // Append a message to the log. network.Log = network.AppendToLog("The network has been defined and stored in the database."); // Check if there is any ID provided. if (!string.IsNullOrEmpty(batchItem.Id)) { // Assign it to the item. network.Id = batchItem.Id; } // Add the new item to the list. networksToAdd.Add(network); } // Create the items. await IEnumerableExtensions.CreateAsync(networksToAdd, serviceProvider, token); // Add the IDs of the created items to the list. ids = ids.Concat(networksToAdd.Select(item => item.Id)); // Use a new scope. using (var scope = serviceProvider.CreateScope()) { // Use a new context instance. using var context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); // Define the new background task. var backgroundTask = new BackgroundTask { DateTimeCreated = DateTime.UtcNow, Name = $"{nameof(IContentTaskManager)}.{nameof(IContentTaskManager.GenerateNetworksAsync)}", IsRecurring = false, Data = JsonSerializer.Serialize(new NetworksTask { Scheme = Scheme, HostValue = HostValue, Items = networksToAdd.Select(item => new NetworkInputModel { Id = item.Id }) }) }; // Mark the task for addition. context.BackgroundTasks.Add(backgroundTask); // Save the changes to the database. await context.SaveChangesAsync(); // Create a new Hangfire background job. BackgroundJob.Enqueue <IContentTaskManager>(item => item.GenerateNetworksAsync(backgroundTask.Id, CancellationToken.None)); } } // Return the IDs of the created items. return(ids); }