/// <summary> /// Constructor /// </summary> public TransferUtils() { Status = new StatusIndicator(); IsErrorState = false; }
/// <summary> /// Handle the click event of the transferButton and initiate the transfer if possible. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void transferButton_Click(object sender, EventArgs e) { try { // save the user-specified parameters for the next run in case they are not already // specified in the App.config Settings.Default.Save(); // optimize the destination connection string for the transfer destination.Text = OptimizeConnectionStringForTransfer(destination.Text); // optimize the source destination connection string for the transfer source.Text = OptimizeConnectionStringForTransfer(source.Text); // reset the transfer utility so we start with a clean slate transferUtils.Reset(); // note the time the transfer started startTime = DateTime.Now; // reset the progress progressBar.Value = 0; tableProgressBar.Value = 0; transferButton.Enabled = false; safeToExit = false; // A list for tables to include in the transfer. This will be populated // with all checked tables in the source and destination grids. List <Table> include = new List <Table>(); // populate the included tables list foreach (DataGridViewRow row in sourceTablesGrid.Rows) { DataGridViewCheckBoxCell checkbox = row.Cells[0] as DataGridViewCheckBoxCell; if (checkbox.Value == checkbox.TrueValue) { IDictionary <string, string> columnMappings = new Dictionary <string, string>(); IDictionary <string, string> virtualSelectColumns = new Dictionary <string, string>(); if (!string.IsNullOrWhiteSpace(row.Cells[3].Value as string)) { // column mappings are in the form of col=>col1,col2=>col3,... foreach (string mapping in (row.Cells[3].Value as string).Replace(" ", "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)) { string[] columns = mapping.Split(new string[] { "=>" }, StringSplitOptions.RemoveEmptyEntries); if (columns.Length != 2) { throw new Exception("Invalid column mapping string: " + mapping); } else { columnMappings.Add(columns[0], columns[1]); } } } // handle virtual select columns if (!string.IsNullOrWhiteSpace(row.Cells[4].Value as string)) { // column mappings are in the form of col=>{select query col1},col2=>{select query col3},... foreach (string column in (row.Cells[4].Value as string).Split(new string[] { "}," }, StringSplitOptions.RemoveEmptyEntries)) { string[] columns = column.Split(new string[] { "=>{" }, StringSplitOptions.RemoveEmptyEntries); if (columns.Length != 2) { throw new Exception("Invalid virtual select column string: " + column); } else { virtualSelectColumns.Add(columns[0], columns[1].Replace("}", "")); } } } // create a table object from the selected row and add it to the included list Table table = new Table(0, row.Cells[1].Value as string, row.Cells[5].Value as string, (int)Math.Round(double.Parse(row.Cells[2].Value as string)), columnMappings, true, virtualSelectColumns); include.Add(table); } } // handle destination tables grid in the same manner foreach (DataGridViewRow row in destinationTablesGrid.Rows) { DataGridViewCheckBoxCell checkbox = row.Cells[0] as DataGridViewCheckBoxCell; if (checkbox.Value == checkbox.TrueValue && !string.IsNullOrWhiteSpace(row.Cells[4].Value as string)) { IDictionary <string, string> virtualSelectColumns = new Dictionary <string, string>(); DataGridViewCheckBoxCell distinct = row.Cells[3] as DataGridViewCheckBoxCell; // handle virtual select columns if (!string.IsNullOrWhiteSpace(row.Cells[4].Value as string)) { // column mappings are in the form of col=>{select query col1},col2=>{select query col3},... foreach (string column in (row.Cells[4].Value as string).Split(new string[] { "}," }, StringSplitOptions.RemoveEmptyEntries)) { string[] columns = column.Split(new string[] { "=>{" }, StringSplitOptions.RemoveEmptyEntries); if (columns.Length != 2) { throw new Exception("Invalid virtual select column string: " + column); } else { virtualSelectColumns.Add(columns[0], columns[1].Replace("}", "")); } } } // create a table object for the selected row and add it to the included list Table table = new Table(0, row.Cells[1].Value as string, null, 0, null, false, virtualSelectColumns, row.Cells[2].Value as string, distinct.Value == distinct.TrueValue); include.Add(table); } } // grab a reference to the transfer utility's status indicator and tie it // to the status controls in the view StatusIndicator status = transferUtils.Status; status.Update += UpdateProgressBar; // prepare the live logging view for use LogView logView = new LogView(); Logger.EntryAdded += logView.LogEntryAdded; logView.SetDesktopLocation(Location.X + 600, Location.Y - 100); logView.Visible = true; // reset the error state error = false; // run the transfer in a background thread new Thread(() => { Thread.CurrentThread.IsBackground = true; try { // no longer safe to exit; the transfer is running safeToExit = false; // perform the transfer transferUtils.TransferTables(source.Text, destination.Text, include, logBox.Text, olderRadio.Checked ? TransferUtils.TransferMode.OlderThan : newerRadio.Checked ? TransferUtils.TransferMode.NewerThan : TransferUtils.TransferMode.All, olderBox.Text, newerBox.Text, includeUndated.Checked, int.Parse(threadsBox.Text), int.Parse(batchBox.Text)); } catch (Exception ex) { MessageBox.Show(ex.Message + ", " + ex.StackTrace); error = true; } finally { // post-transfer/post-failure housekeeping status.Update -= UpdateProgressBar; safeToExit = true; Logger.EntryAdded -= logView.LogEntryAdded; transferButton.Enabled = true; } }).Start(); // Run a polling-based status updater in a background thread. It would // be nice to replace this with a responsive programming approach like // RX. Thread memoryUpdater = new Thread(() => { while (!safeToExit) { try { UpdateTableProgress(); UpdateQueryThreads(); UpdateETA(); InvokeUpdateCurrentHealth(); InvokeUpdateRecentHealth(); InvokeUpdateOverallHealth(); Thread.Sleep(100); } catch (Exception ex) { MessageBox.Show(ex.Message + ", " + ex.StackTrace); error = true; } } }); memoryUpdater.Start(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error"); } }