private static void ImportCsvToDatabase(ApplianceDbContext db, string partsFilePath) { var parts = CsvDataLoader.LoadPartsFromCsv(partsFilePath); db.AddRange(parts); db.SaveChanges(); }
private static async Task UpdateItemsFromDatabase(bool uploadModifiedOnly) { if (_currentConnection == null) { Output.WriteLine(Output.Warning, "No connection selected. Please create a new connection or select an existing connection."); return; } List <AppliancePart> partsToUpload = null; List <AppliancePart> partsToDelete = null; var newUploadTime = DateTime.UtcNow; using (var db = new ApplianceDbContext()) { if (uploadModifiedOnly) { // Load the last upload timestamp var lastUploadTime = GetLastUploadTime(); Output.WriteLine(Output.Info, $"Uploading changes since last upload at {lastUploadTime.ToLocalTime().ToString()}"); partsToUpload = db.Parts .Where(p => EF.Property <DateTime>(p, "LastUpdated") > lastUploadTime) .ToList(); partsToDelete = db.Parts .IgnoreQueryFilters() // Normally items with IsDeleted = 1 aren't included in queries .Where(p => (EF.Property <bool>(p, "IsDeleted") && EF.Property <DateTime>(p, "LastUpdated") > lastUploadTime)) .ToList(); } else { partsToUpload = db.Parts .ToList(); partsToDelete = db.Parts .IgnoreQueryFilters() // Normally items with IsDeleted = 1 aren't included in queries .Where(p => EF.Property <bool>(p, "IsDeleted")) .ToList(); } } Output.WriteLine(Output.Info, $"Processing {partsToUpload.Count()} add/updates, {partsToDelete.Count()} deletes"); bool success = true; foreach (var part in partsToUpload) { var newItem = new ExternalItem { Id = part.PartNumber.ToString(), Content = new ExternalItemContent { // Need to set to null, service returns 400 // if @odata.type property is sent ODataType = null, Type = ExternalItemContentType.Text, Value = part.Description }, Acl = new List <Acl> { new Acl { AccessType = AccessType.Grant, Type = AclType.Everyone, Value = _tenantId, IdentitySource = "Azure Active Directory" } }, Properties = part.AsExternalItemProperties() }; try { Output.Write(Output.Info, $"Uploading part number {part.PartNumber}..."); await _graphHelper.AddOrUpdateItem(_currentConnection.Id, newItem); Output.WriteLine(Output.Success, "DONE"); } catch (ServiceException serviceException) { success = false; Output.WriteLine(Output.Error, "FAILED"); Output.WriteLine(Output.Error, $"{serviceException.StatusCode} error adding or updating part {part.PartNumber}"); Output.WriteLine(Output.Error, serviceException.Message); } } foreach (var part in partsToDelete) { try { Output.Write(Output.Info, $"Deleting part number {part.PartNumber}..."); await _graphHelper.DeleteItem(_currentConnection.Id, part.PartNumber.ToString()); Output.WriteLine(Output.Success, "DONE"); } catch (ServiceException serviceException) { if (serviceException.StatusCode.Equals(System.Net.HttpStatusCode.NotFound)) { Output.WriteLine(Output.Warning, "Not found"); } else { success = false; Output.WriteLine(Output.Error, "FAILED"); Output.WriteLine(Output.Error, $"{serviceException.StatusCode} error deleting part {part.PartNumber}"); Output.WriteLine(Output.Error, serviceException.Message); } } } // If no errors, update our last upload time if (success) { SaveLastUploadTime(newUploadTime); } }
static async Task Main(string[] args) { try { Output.WriteLine("Parts Inventory Search Connector\n"); // Load configuration from appsettings.json var appConfig = LoadAppSettings(); if (appConfig == null) { Output.WriteLine(Output.Error, "Missing or invalid user secrets"); Output.WriteLine(Output.Error, "Please see README.md for instructions on configuring the application."); return; } // Save tenant ID for setting ACL on items _tenantId = appConfig["tenantId"]; // Initialize the auth provider var authProvider = new ClientCredentialAuthProvider( appConfig["appId"], appConfig["tenantId"], appConfig["appSecret"] ); // Check if the database is empty using (var db = new ApplianceDbContext()) { if (db.Parts.IgnoreQueryFilters().Count() <= 0) { Output.WriteLine(Output.Warning, "Database empty, importing entries from CSV file"); ImportCsvToDatabase(db, "ApplianceParts.csv"); } } _graphHelper = new GraphHelper(authProvider); do { var userChoice = DoMenuPrompt(); switch (userChoice) { case MenuChoice.CreateConnection: await CreateConnectionAsync(); break; case MenuChoice.ChooseExistingConnection: await SelectExistingConnectionAsync(); break; case MenuChoice.DeleteConnection: await DeleteCurrentConnectionAsync(); break; case MenuChoice.RegisterSchema: await RegisterSchemaAsync(); break; case MenuChoice.ViewSchema: await GetSchemaAsync(); break; case MenuChoice.PushUpdatedItems: await UpdateItemsFromDatabase(true); break; case MenuChoice.PushAllItems: await UpdateItemsFromDatabase(false); break; case MenuChoice.Exit: // Exit the program Output.WriteLine("Goodbye..."); return; case MenuChoice.Invalid: default: Output.WriteLine(Output.Warning, "Invalid choice! Please try again."); break; } Output.WriteLine(""); } while (true); } catch (Exception ex) { Output.WriteLine(Output.Error, "An unexpected exception occurred."); Output.WriteLine(Output.Error, ex.Message); Output.WriteLine(Output.Error, ex.StackTrace); } }