Пример #1
0
        private async void MenuItemMergeDatabases_Click(object sender, RoutedEventArgs e)
        {
            if (this.State.SuppressMergeDatabasesPrompt == false)
            {
                if (Dialogs.MenuFileMergeDatabasesExplainedDialog(this) == false)
                {
                    return;
                }
            }
            // Get the location of the template, which also determines the root folder
            if (this.TryGetTemplatePath(out string templateDatabasePath) == false)
            {
                return;
            }

            // Set up progress indicators
            Mouse.OverrideCursor = Cursors.Wait;
            this.StatusBar.SetMessage("Creating a merged database, please wait...");
            IProgress <ProgressBarArguments> progress = progressHandler;

            this.BusyCancelIndicator.EnableForMerging(true);

            // Find all the .DDB files located in subfolders under the root folder (excluding backup folders)
            string        startFolder = Path.GetDirectoryName(templateDatabasePath);
            List <string> allDDBFiles = new List <string>();

            FilesFolders.GetAllFilesInFoldersAndSubfoldersMatchingPattern(startFolder, "*" + Constant.File.FileDatabaseFileExtension, true, true, allDDBFiles);

            // Merge the found databases into a new (or replaced) TimelapseData_merged.ddb file located in the same folder as the template.
            // Note: .ddb files found in a Backup folder will be ignored
            ErrorsAndWarnings errorMessages = await MergeDatabases.TryMergeDatabasesAsync(templateDatabasePath, allDDBFiles, progress).ConfigureAwait(true);

            // Turn off progress indicators
            this.BusyCancelIndicator.EnableForSelection(false);
            Mouse.OverrideCursor = null;

            if (errorMessages.Errors.Count != 0 || errorMessages.Warnings.Count != 0)
            {
                // Merge databases: Show errors and/or warnings, if any.
                Dialogs.MenuFileMergeDatabasesErrorsAndWarningsDialog(this, errorMessages);
            }
            this.StatusBar.SetMessage(errorMessages.Errors.Count == 0 ? "Merged database created" : "Aborted creation of merged database");
        }
Пример #2
0
        // Given
        // - a path to a .tdb file  (specifying the root folder)
        // - a list of ddbFiles (which must be located in sub-folders relative to the root folder)
        // create a .ddb File in the root folder that merges data found in the .ddbFiles into it, in particular, the tables:
        // - DataTable
        // - Detections
        // If fatal errors occur in the merge, abort
        // Return the relevant error messages in the ErrorsAndWarnings object.
        // Note: if a merged .ddb File already exists in that root folder, it will be backed up and then over-written

        public async static Task <ErrorsAndWarnings> TryMergeDatabasesAsync(string tdbFile, List <string> sourceDDBFilePaths, IProgress <ProgressBarArguments> progress)
        {
            ErrorsAndWarnings errorMessages = new ErrorsAndWarnings();

            string rootFolderPath         = Path.GetDirectoryName(tdbFile);
            string destinationDDBFileName = Constant.File.MergedFileName;
            string destinationDDBFilePath = Path.Combine(rootFolderPath, destinationDDBFileName);
            string rootFolderName         = rootFolderPath.Split(Path.DirectorySeparatorChar).Last();


            if (sourceDDBFilePaths == null)
            {
                errorMessages.Errors.Add("No databases (.ddb files) were found in the sub-folders, so there was nothing to merge.");
                return(errorMessages);
            }

            // if the mergedatabase file was previously created, it may be included in the source list.
            // So just skip over it, as it no longer exists and we don't actually want it
            sourceDDBFilePaths.RemoveAll(Item => Item == destinationDDBFilePath);

            if (sourceDDBFilePaths.Count == 0)
            {
                errorMessages.Errors.Add("No databases (.ddb files) were found in the sub-folders, so there was nothing to merge.");
                return(errorMessages);
            }

            // Check to see if we can actually open the template.
            // As we can't have out parameters in an async method, we return the state and the desired templateDatabase as a tuple
            // Original form: if (!(await TemplateDatabase.TryCreateOrOpenAsync(templateDatabasePath, out this.templateDatabase).ConfigureAwait(true))
            Tuple <bool, TemplateDatabase> tupleResult = await TemplateDatabase.TryCreateOrOpenAsync(tdbFile).ConfigureAwait(true);

            TemplateDatabase templateDatabase = tupleResult.Item2;

            if (!tupleResult.Item1)
            {
                // notify the user the template couldn't be loaded rather than silently doing nothing
                errorMessages.Errors.Add("Could not open the template .tdb file: " + tdbFile);
                return(errorMessages);
            }

            // if the merge file exists, move it to the backup folder as we will be overwriting it.
            bool backupMade = false;

            if (File.Exists(destinationDDBFilePath))
            {
                // Backup the old merge file by moving it to the backup folder
                // Note that we do the move instead of copy as we will be overwriting the file anyways
                backupMade = FileBackup.TryCreateBackup(destinationDDBFilePath, true);
            }

            FileDatabase fd = await FileDatabase.CreateEmptyDatabase(destinationDDBFilePath, templateDatabase).ConfigureAwait(true);

            fd.Dispose();
            fd = null;

            // Open the database
            SQLiteWrapper destinationDDB = new SQLiteWrapper(destinationDDBFilePath);

            // Get the DataLabels from the DataTable in the main database.
            // We will later check to see if they match their counterparts in each database to merge in
            List <string> mergedDDBDataLabels = destinationDDB.SchemaGetColumns(Constant.DBTables.FileData);

            int sourceDDBFilePathsCount = sourceDDBFilePaths.Count;

            for (int i = 0; i < sourceDDBFilePathsCount; i++)
            {
                if (sourceDDBFilePaths[i].Equals(destinationDDBFilePath))
                {
                    // if the mergedatabase file was previously created, it may be included in the source list.
                    // So just skip over it, as it no longer exists and we don't actually want it
                    continue;
                }

                // Try to merge each database into the merged database
                await Task.Run(() =>
                {
                    // Report progress, introducing a delay to allow the UI thread to update and to make the progress bar linger on the display
                    progress.Report(new ProgressBarArguments((int)((i + 1) / (double)sourceDDBFilePathsCount * 100.0),
                                                             String.Format("Merging {0}/{1} databases. Please wait...", i + 1, sourceDDBFilePathsCount),
                                                             "Merging...",
                                                             false, false));
                    Thread.Sleep(250);
                    ListComparisonEnum listComparisonEnum = MergeDatabases.InsertSourceDataBaseTablesintoDestinationDatabase(destinationDDB, sourceDDBFilePaths[i], rootFolderPath, mergedDDBDataLabels);
                    if (listComparisonEnum != ListComparisonEnum.Identical)
                    {
                        string message = listComparisonEnum == ListComparisonEnum.ElementsDiffer
                        ? "Its template uses different data labels"
                        : "Its template has the same data labels, but in a different order";
                        string trimmedPath = sourceDDBFilePaths[i].Substring(rootFolderPath.Length + 1);
                        errorMessages.Warnings.Add(String.Format("'{0}' was skipped. {1}", trimmedPath, message));
                    }
                }).ConfigureAwait(true);
            }
            // After the merged database is constructed, set the Folder column to the current root folder
            if (!String.IsNullOrEmpty(rootFolderName))
            {
                destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.FileData + Sql.Set + Constant.DatabaseColumn.Folder + Sql.Equal + Sql.Quote(rootFolderName));
            }

            // After the merged database is constructed, reset fields in the ImageSetTable to the defaults i.e., first row, selection all,
            if (!String.IsNullOrEmpty(rootFolderName))
            {
                destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.ImageSet + Sql.Set + Constant.DatabaseColumn.MostRecentFileID + Sql.Equal + "1");
                destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.ImageSet + Sql.Set + Constant.DatabaseColumn.Selection + Sql.Equal + ((int)FileSelectionEnum.All).ToString());
                destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.ImageSet + Sql.Set + Constant.DatabaseColumn.SortTerms + Sql.Equal + Sql.Quote(Constant.DatabaseValues.DefaultSortTerms));
            }
            if (backupMade && (errorMessages.Errors.Any() || errorMessages.Warnings.Any()))
            {
                errorMessages.Warnings.Add(String.Format("Note: A backup of your original {0} can be found in the {1} folder", destinationDDBFileName, Constant.File.BackupFolder));
            }
            return(errorMessages);
        }