//---------------------------------------------------------------------
        // CHANGED: CR39 (Split and merge complete messages)
        // Return true or false success so the main class knows
        // whether to notify the user following the completion of
        // the merge.
        //
        private bool PerformPhysicalMerge()
        {
            bool success = true;
            try
            {
                HluDataSet.incid_mm_polygonsDataTable selectTable = new HluDataSet.incid_mm_polygonsDataTable();
                _viewModelMain.GetIncidMMPolygonRows(ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                    _viewModelMain.GisSelection.Select(), _viewModelMain.GisIDColumnOrdinals,
                    ViewModelWindowMain.IncidPageSize, selectTable), ref selectTable);

                if (selectTable.Count == 0)
                    return false;
                else if (selectTable.Count != _viewModelMain.GisSelection.Rows.Count)
                    throw new Exception(String.Format("GIS Layer and database are out of sync:\n{0} map polygons, {1} rows in table {2}.",
                        _viewModelMain.FragsSelectedMapCount, selectTable.Count, _viewModelMain.HluDataset.incid_mm_polygons.TableName));

                // lowest toid_fragment_id in selection assigned to result feature
                string newToidFragmentID = selectTable.Min(r => r.toid_fragment_id);

                if (selectTable.GroupBy(r => r.incid).Count() == 1)
                {
                    int minFragmID = Int32.Parse(newToidFragmentID);
                    _mergeResultFeatureIndex = selectTable.Select((r, index) =>
                        Int32.Parse(r.toid_fragment_id) == minFragmID ? index : -1).First(i => i != -1);
                }
                else
                {
                    _mergeFeaturesWindow = new WindowMergeFeatures();
                    _mergeFeaturesWindow.Owner = App.Current.MainWindow;
                    _mergeFeaturesWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;

                    _mergeFeaturesViewModelPhysical = new ViewModelMergeFeatures
                        <HluDataSet.incid_mm_polygonsDataTable, HluDataSet.incid_mm_polygonsRow>(selectTable,
                        _viewModelMain.GisIDColumnOrdinals, _viewModelMain.IncidTable.incidColumn.Ordinal,
                        null, _viewModelMain.GISApplication);
                    _mergeFeaturesViewModelPhysical.DisplayName = "Select Feature To Keep";
                    _mergeFeaturesViewModelPhysical.RequestClose += new ViewModelMergeFeatures
                        <HluDataSet.incid_mm_polygonsDataTable, HluDataSet.incid_mm_polygonsRow>
                        .RequestCloseEventHandler(_mergeFeaturesViewModelPhysical_RequestClose);

                    _mergeFeaturesWindow.DataContext = _mergeFeaturesViewModelPhysical;
                    _mergeResultFeatureIndex = -1;

                    _mergeFeaturesWindow.ShowDialog();
                }

                if (_mergeResultFeatureIndex != -1)
                {
                    _viewModelMain.ChangeCursor(Cursors.Wait, "Processing ...");
                    bool startTransaction = _viewModelMain.DataBase.Transaction != null;

                    if (startTransaction)
                        _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);

                    try
                    {
                        _viewModelMain.ViewModelUpdate.UpdateIncidModifiedColumns(_viewModelMain.IncidsSelectedMap.ElementAt(0));

                        List<List<SqlFilterCondition>> resultFeatureWhereClause =
                            ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                            new HluDataSet.incid_mm_polygonsRow[] { selectTable[_mergeResultFeatureIndex] },
                                _viewModelMain.GisIDColumnOrdinals, ViewModelWindowMain.IncidPageSize, selectTable);

                        if (resultFeatureWhereClause.Count != 1)
                            throw new Exception("Error getting result feature from database.");

                        List<List<SqlFilterCondition>> mergeFeaturesWhereClause =
                            ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                            selectTable.Where((r, index) => index != _mergeResultFeatureIndex).ToArray(),
                                _viewModelMain.GisIDColumnOrdinals, ViewModelWindowMain.IncidPageSize, selectTable);

                        // historyTable contains rows of features merged into result feature (i.e. no longer existing)
                        // and last row with data of result feature (remaining in GIS, lowest toid_fragment_id of merged features)
                        // this last row must be removed before writing history
                        // but is needed to update geometry fields in incid_mm_polygons
                        DataTable historyTable = _viewModelMain.GISApplication.MergeFeatures(newToidFragmentID,
                            resultFeatureWhereClause[0].Select(c => c.Clone()).ToList(), _viewModelMain.HistoryColumns);

                        if (historyTable == null)
                            throw new Exception("GIS merge operation failed.");

                        DataTable resultTable = historyTable.Clone();
                        DataRow resultRow = historyTable.AsEnumerable().FirstOrDefault(r =>
                            r.Field<string>(_viewModelMain.HluDataset.history.toid_fragment_idColumn.ColumnName) == newToidFragmentID);
                        if (resultRow == null) throw new Exception(String.Format(
                            "Failed to obtain geometry data of result feature from {0}.", _viewModelMain.GISApplication.ApplicationType));
                        resultTable.LoadDataRow(resultRow.ItemArray, true);
                        resultRow.Delete();
                        historyTable.AcceptChanges();

                        // synchronize DB shadow copy of GIS layer
                        MergeSynchronizeIncidMMPolygons(selectTable, resultTable, newToidFragmentID,
                            resultFeatureWhereClause[0], mergeFeaturesWhereClause);

                        // insert history rows (fixed values incid, toid, newToidFragmentID)
                        Dictionary<int, string> fixedValues = new Dictionary<int, string>();
                        fixedValues.Add(_viewModelMain.HluDataset.history.incidColumn.Ordinal, selectTable[0].incid);
                        fixedValues.Add(_viewModelMain.HluDataset.history.toidColumn.Ordinal, selectTable[0].toid);
                        fixedValues.Add(_viewModelMain.HluDataset.history.toid_fragment_idColumn.Ordinal, newToidFragmentID);
                        ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                        vmHist.HistoryWrite(fixedValues, historyTable, ViewModelWindowMain.Operations.PhysicalMerge);

                        if (startTransaction)
                        {
                            _viewModelMain.DataBase.CommitTransaction();
                            _viewModelMain.HluDataset.AcceptChanges();
                        }

                        // Re-count the incid records in the database.
                        _viewModelMain.IncidRowCount(true);

                        // Reset the incid and map selections but don't move
                        // to the first incid in the database.
                        _viewModelMain.ClearFilter(false);

                        // Synch with the GIS selection.
                        //---------------------------------------------------------------------
                        // FIX: 027 Force refill of Incid table after split/merge
                        // Force the Incid table to be refilled because it has been
                        // updated directly in the database rather than via the
                        // local copy.
                        _viewModelMain.RefillIncidTable = true;
                        //---------------------------------------------------------------------
                        _viewModelMain.ReadMapSelection(true);
                    }
                    catch
                    {
                        if (startTransaction) _viewModelMain.DataBase.RollbackTransaction();
                        throw;
                    }
                }
            }
            catch (Exception ex)
            {
                success = false;
                MessageBox.Show("Merge operation failed. The error message returned was:\n\n" +
                    ex.Message, "HLU Merge Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally { _viewModelMain.ChangeCursor(Cursors.Arrow, null); }
            return success;
        }
        /// <summary>
        /// Writes changes made to current incid back to database and GIS layer.
        /// Also synchronizes shadow copy of GIS layer in DB and writes history.
        /// </summary>
        internal bool Update()
        {
            _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);

            try
            {
                _viewModelMain.ChangeCursor(Cursors.Wait, "Saving ...");

                int incidCurrRowIx = _viewModelMain.IncidCurrentRowIndex;

                //---------------------------------------------------------------------
                // FIXED: KI97 (Last modified date and user)
                // CHANGED: CR3 (IHS version)
                // Previously only changes to fields on the incid table triggered the
                // last modified date & user fields to be updated.
                // Update the last modified date & user fields and the ihs version on
                // the incid table regardless of which attributes have been changed.
                //if (_viewModelMain.IsDirtyIncid())
                //{
                IncidCurrentRowDerivedValuesUpdate(_viewModelMain);

                //---------------------------------------------------------------------
                // FIX: 028 Only update DateTime fields to whole seconds
                // Fractions of a second can cause rounding differences when
                // comparing DateTime fields later in some databases.
                DateTime currDtTm = DateTime.Now;
                DateTime nowDtTm  = new DateTime(currDtTm.Year, currDtTm.Month, currDtTm.Day, currDtTm.Hour, currDtTm.Minute, currDtTm.Second, DateTimeKind.Local);
                //---------------------------------------------------------------------
                _viewModelMain.IncidCurrentRow.last_modified_date    = nowDtTm;
                _viewModelMain.IncidCurrentRow.last_modified_user_id = _viewModelMain.UserID;
                _viewModelMain.IncidCurrentRow.ihs_version           = _viewModelMain.IhsVersion;

                if (_viewModelMain.HluTableAdapterManager.incidTableAdapter.Update(
                        (HluDataSet.incidDataTable)_viewModelMain.HluDataset.incid.GetChanges()) == -1)
                {
                    throw new Exception(String.Format("Failed to update '{0}' table.",
                                                      _viewModelMain.HluDataset.incid.TableName));
                }
                //}
                //---------------------------------------------------------------------

                if ((_viewModelMain.IncidIhsMatrixRows != null) && _viewModelMain.IsDirtyIncidIhsMatrix())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_matrixTableAdapter.Update(
                            (HluDataSet.incid_ihs_matrixDataTable)_viewModelMain.HluDataset.incid_ihs_matrix.GetChanges()) == -1)
                    {
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                                                          _viewModelMain.HluDataset.incid_ihs_matrix.TableName));
                    }
                }

                if ((_viewModelMain.IncidIhsFormationRows != null) && _viewModelMain.IsDirtyIncidIhsFormation())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_formationTableAdapter.Update(
                            (HluDataSet.incid_ihs_formationDataTable)_viewModelMain.HluDataset.incid_ihs_formation.GetChanges()) == -1)
                    {
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                                                          _viewModelMain.HluDataset.incid_ihs_formation.TableName));
                    }
                }

                if ((_viewModelMain.IncidIhsManagementRows != null) && _viewModelMain.IsDirtyIncidIhsManagement())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_managementTableAdapter.Update(
                            (HluDataSet.incid_ihs_managementDataTable)_viewModelMain.HluDataset.incid_ihs_management.GetChanges()) == -1)
                    {
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                                                          _viewModelMain.HluDataset.incid_ihs_management.TableName));
                    }
                }

                if ((_viewModelMain.IncidIhsComplexRows != null) && _viewModelMain.IsDirtyIncidIhsComplex())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_complexTableAdapter.Update(
                            (HluDataSet.incid_ihs_complexDataTable)_viewModelMain.HluDataset.incid_ihs_complex.GetChanges()) == -1)
                    {
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                                                          _viewModelMain.HluDataset.incid_ihs_complex.TableName));
                    }
                }

                if (_viewModelMain.IsDirtyIncidBap())
                {
                    UpdateBap();
                }

                if (_viewModelMain.IncidSourcesRows != null)
                {
                    int j = 0;
                    for (int i = 0; i < _viewModelMain.IncidSourcesRows.Length; i++)
                    {
                        if (_viewModelMain.IncidSourcesRows[i] != null)
                        {
                            _viewModelMain.IncidSourcesRows[i].sort_order = ++j;
                        }
                    }

                    if (_viewModelMain.HluTableAdapterManager.incid_sourcesTableAdapter.Update(
                            (HluDataSet.incid_sourcesDataTable)_viewModelMain.IncidSourcesTable.GetChanges()) == -1)
                    {
                        throw new Exception(String.Format("Failed to update {0} table.",
                                                          _viewModelMain.HluDataset.incid_sources.TableName));
                    }
                }

                // update all GIS rows corresponding to this incid
                List <SqlFilterCondition> incidCond = new List <SqlFilterCondition>(new SqlFilterCondition[] {
                    new SqlFilterCondition(_viewModelMain.HluDataset.incid_mm_polygons,
                                           _viewModelMain.HluDataset.incid_mm_polygons.incidColumn, _viewModelMain.Incid)
                });

                var q = _viewModelMain.HluDataset.lut_ihs_habitat
                        .Where(r => r.code == _viewModelMain.IncidCurrentRow.ihs_habitat);
                string ihsHabitatCategory = q.Count() == 1 ? q.ElementAt(0).category : null;

                DataTable historyTable = _viewModelMain.GISApplication.UpdateFeatures(new DataColumn[] {
                    _viewModelMain.HluDataset.incid_mm_polygons.ihs_categoryColumn,
                    _viewModelMain.HluDataset.incid_mm_polygons.ihs_summaryColumn
                },
                                                                                      new object[] { ihsHabitatCategory, _viewModelMain.IncidIhsSummary },
                                                                                      _viewModelMain.HistoryColumns, incidCond);

                if (historyTable == null)
                {
                    throw new Exception("Error updating GIS layer.");
                }
                else if (historyTable.Rows.Count == 0)
                {
                    throw new Exception("No GIS features to update.");
                }

                // likewise update DB shadow copy of GIS layer
                if (_viewModelMain.DataBase.ExecuteNonQuery(String.Format("UPDATE {0} SET {1} = {3}, {2} = {4} WHERE {5}",
                                                                          _viewModelMain.DataBase.QualifyTableName(_viewModelMain.HluDataset.incid_mm_polygons.TableName),
                                                                          _viewModelMain.DataBase.QuoteIdentifier(
                                                                              _viewModelMain.HluDataset.incid_mm_polygons.ihs_categoryColumn.ColumnName),
                                                                          _viewModelMain.DataBase.QuoteIdentifier(
                                                                              _viewModelMain.HluDataset.incid_mm_polygons.ihs_summaryColumn.ColumnName),
                                                                          _viewModelMain.DataBase.QuoteValue(ihsHabitatCategory),
                                                                          _viewModelMain.DataBase.QuoteValue(_viewModelMain.IncidIhsSummary),
                                                                          _viewModelMain.DataBase.WhereClause(false, true, true, incidCond)),
                                                            _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text) == -1)
                {
                    throw new Exception("Failed to update database copy of GIS layer.");
                }

                // save history returned from GIS
                Dictionary <int, string> fixedValues = new Dictionary <int, string>();
                fixedValues.Add(_viewModelMain.HluDataset.history.incidColumn.Ordinal, _viewModelMain.Incid);
                ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                vmHist.HistoryWrite(fixedValues, historyTable, ViewModelWindowMain.Operations.AttributeUpdate);

                _viewModelMain.DataBase.CommitTransaction();
                _viewModelMain.HluDataset.AcceptChanges();
                _viewModelMain.Saved = true;

                _viewModelMain.IncidRowCount(true);
                _viewModelMain.IncidCurrentRowIndex = incidCurrRowIx;

                return(true);
            }
            catch (Exception ex)
            {
                _viewModelMain.DataBase.RollbackTransaction();
                if (_viewModelMain.HaveGisApp)
                {
                    _viewModelMain.Saved = false;
                    MessageBox.Show("Your changes could not be saved. The error message returned was:\n\n" +
                                    ex.Message, "HLU: Save Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            finally
            {
                _viewModelMain.SavingAttempted = true;
                _viewModelMain.Saving          = false;
                _viewModelMain.ChangeCursor(Cursors.Arrow, null);
            }
        }
        //---------------------------------------------------------------------
        //---------------------------------------------------------------------
        // CHANGED: CR39 (Split and merge complete messages)
        // Return true or false success so the main class knows
        // whether to notify the user following the completion of
        // the merge.
        //
        private bool PerformLogicalMerge(bool physicallyMerge)
        {
            bool success = true;
            try
            {
                if (_viewModelMain.IncidsSelectedMapCount <= 0)
                    return false;

                _mergeFeaturesWindow = new WindowMergeFeatures();
                _mergeFeaturesWindow.Owner = App.Current.MainWindow;
                _mergeFeaturesWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                _mergeFeaturesWindow.MaxHeight = App.Current.MainWindow.ActualHeight;

                HluDataSet.incidDataTable selectTable = new HluDataSet.incidDataTable();
                _viewModelMain.HluTableAdapterManager.incidTableAdapter.Fill(selectTable,
                    ViewModelWindowMainHelpers.IncidSelectionToWhereClause(ViewModelWindowMain.IncidPageSize,
                    _viewModelMain.IncidTable.incidColumn.Ordinal, _viewModelMain.IncidTable, _viewModelMain.IncidsSelectedMap));

                HluDataSet.incid_mm_polygonsDataTable polygons = new HluDataSet.incid_mm_polygonsDataTable();
                _viewModelMain.GetIncidMMPolygonRows(ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                    _viewModelMain.GisSelection.Select(), _viewModelMain.GisIDColumnOrdinals,
                    ViewModelWindowMain.IncidPageSize, polygons), ref polygons);

                _mergeFeaturesViewModelLogical = new ViewModelMergeFeatures<HluDataSet.incidDataTable,
                    HluDataSet.incidRow>(selectTable, _viewModelMain.GisIDColumnOrdinals,
                    _viewModelMain.IncidTable.incidColumn.Ordinal, polygons.Select(r => r).ToArray(),
                    _viewModelMain.GISApplication);
                _mergeFeaturesViewModelLogical.DisplayName = "Select INCID To Keep";
                _mergeFeaturesViewModelLogical.RequestClose += new ViewModelMergeFeatures<HluDataSet.incidDataTable,
                        HluDataSet.incidRow>.RequestCloseEventHandler(_mergeFeaturesViewModelLogical_RequestClose);

                _mergeFeaturesWindow.DataContext = _mergeFeaturesViewModelLogical;
                _mergeResultFeatureIndex = -1;

                _mergeFeaturesWindow.ShowDialog();

                if (_mergeResultFeatureIndex == -1)
                    return false;

                _viewModelMain.ChangeCursor(Cursors.Wait, "Processing ...");

                _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);

                try
                {
                    string keepIncid = selectTable[_mergeResultFeatureIndex].incid;

                    // assign selected incid to selected features except keepIncid
                    DataTable historyTable = _viewModelMain.GISApplication.MergeFeaturesLogically(
                        keepIncid, _viewModelMain.HistoryColumns);

                    if ((historyTable == null) || (historyTable.Rows.Count == 0))
                        throw new Exception("Failed to update GIS layer.");

                    // assign selected incid and new toid_fragment_id to selected features except keepIncid in DB shadow copy
                    string toidFragmentFormat = String.Format("D{0}",
                        _viewModelMain.HluDataset.incid_mm_polygons.toid_fragment_idColumn.MaxLength);

                    List<KeyValuePair<int, object>> updateFields = new List<KeyValuePair<int,object>>();
                    var keepPolygon = polygons.FirstOrDefault(r => r.incid == keepIncid);
                    if (keepPolygon != null)
                    {
                        updateFields = (from c in polygons.Columns.Cast<DataColumn>()
                                        where (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.incidColumn.Ordinal) &&
                                            (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.toidColumn.Ordinal) &&
                                            (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.toid_fragment_idColumn.Ordinal) &&
                                            (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.shape_lengthColumn.Ordinal) &&
                                            (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.shape_areaColumn.Ordinal)
                                        select new KeyValuePair<int, object>(c.Ordinal, keepPolygon[c.Ordinal])).ToList();
                    }

                    var updatePolygons = from r in polygons
                                            where r.incid != keepIncid
                                            orderby r.toid, r.toid_fragment_id
                                            select r;

                    // update shadow DB copy of GIS layer
                    foreach (HluDataSet.incid_mm_polygonsRow r in updatePolygons)
                    {
                        r.incid = keepIncid;
                        for (int i = 0; i < updateFields.Count; i++)
                            r[updateFields[i].Key] = updateFields[i].Value;
                    }

                    if (_viewModelMain.HluTableAdapterManager.incid_mm_polygonsTableAdapter.Update(polygons) == -1)
                        throw new Exception(String.Format("Failed to update {0} table.", _viewModelMain.HluDataset.incid_mm_polygons.TableName));

                    // insert history rows (fixed value keepIncid)
                    Dictionary<int, string> fixedValues = new Dictionary<int, string>();
                    fixedValues.Add(_viewModelMain.HluDataset.history.incidColumn.Ordinal, keepIncid);
                    ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                    vmHist.HistoryWrite(fixedValues, historyTable, ViewModelWindowMain.Operations.LogicalMerge);

                    // count incid records no longer in use
                    List<string> deleteIncids = new List<string>();

                    IDataReader delReader = _viewModelMain.DataBase.ExecuteReader(String.Format(
                        "SELECT {0} FROM {1} WHERE {0} IN ({2}) GROUP BY {0} HAVING COUNT(*) = 0",
                        _viewModelMain.DataBase.QuoteIdentifier(_viewModelMain.IncidTable.incidColumn.ColumnName),
                        _viewModelMain.DataBase.QualifyTableName(_viewModelMain.IncidTable.TableName),
                        selectTable.Aggregate(new StringBuilder(), (sb, r) => sb.Append("," +
                            _viewModelMain.DataBase.QuoteValue(r.incid))).Remove(0, 1)),
                        _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text);

                    if (delReader == null) throw new Exception("Error reading incid database table.");

                    while (delReader.Read())
                        deleteIncids.Add(delReader.GetString(0));
                    delReader.Close();

                    // delete any incid records no longer in use
                    if (deleteIncids.Count > 0)
                    {
                        int numAffected = _viewModelMain.DataBase.ExecuteNonQuery(String.Format(
                            "DELETE FROM {0} WHERE {1} IN ({2})",
                            _viewModelMain.DataBase.QualifyTableName(_viewModelMain.HluDataset.incid.TableName),
                            _viewModelMain.DataBase.QuoteValue(_viewModelMain.HluDataset.incid.incidColumn.ColumnName),
                            String.Join(",", deleteIncids.Select(i => _viewModelMain.DataBase.QuoteValue(i)).ToArray())),
                            _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text);

                        if (numAffected > 0) _viewModelMain.IncidRowCount(true);
                    }

                    _viewModelMain.ViewModelUpdate.UpdateIncidModifiedColumns(keepIncid);

                    if (physicallyMerge && (MessageBox.Show("Perform physical merge as well?", "HLU: Physical Merge",
                        MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes))
                    {
                        // restore the selection
                        _viewModelMain.GisSelection.Clear();
                        foreach (HluDataSet.incid_mm_polygonsRow r in polygons)
                        {
                            DataRow newRow = _viewModelMain.GisSelection.NewRow();
                            for (int i = 0; i < _viewModelMain.GisIDColumnOrdinals.Length; i++)
                                newRow[i] = r[_viewModelMain.GisIDColumnOrdinals[i]];
                            _viewModelMain.GisSelection.Rows.Add(newRow);
                        }

                        PerformPhysicalMerge();
                    }
                    else
                    {
                        _viewModelMain.DataBase.CommitTransaction();
                        _viewModelMain.HluDataset.AcceptChanges();

                        // Re-count the incid records in the database.
                        _viewModelMain.IncidRowCount(true);

                        // Reset the incid and map selections but don't move
                        // to the first incid in the database.
                        _viewModelMain.ClearFilter(false);

                        // Synch with the GIS selection.
                        //---------------------------------------------------------------------
                        // FIX: 027 Force refill of Incid table after split/merge
                        // Force the Incid table to be refilled because it has been
                        // updated directly in the database rather than via the
                        // local copy.
                        _viewModelMain.RefillIncidTable = true;
                        //---------------------------------------------------------------------
                        _viewModelMain.ReadMapSelection(true);
                    }
                }
                catch
                {
                    _viewModelMain.DataBase.RollbackTransaction();
                    throw;
                }
            }
            catch (Exception ex)
            {
                success = false;
                MessageBox.Show("Merge operation failed. The error message returned was:\n\n" +
                    ex.Message, "HLU Merge Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally { _viewModelMain.ChangeCursor(Cursors.Arrow, null); }
            return success;
        }
        /// <summary>
        /// Writes changes made to current incid back to database and GIS layer.
        /// Also synchronizes shadow copy of GIS layer in DB and writes history.
        /// </summary>
        internal bool Update()
        {
            _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);

            try
            {
                _viewModelMain.ChangeCursor(Cursors.Wait, "Saving ...");

                int incidCurrRowIx = _viewModelMain.IncidCurrentRowIndex;

                if (_viewModelMain.IsDirtyIncid())
                {
                    IncidCurrentRowDerivedValuesUpdate(_viewModelMain);

                    _viewModelMain.IncidCurrentRow.last_modified_date = DateTime.Now;
                    _viewModelMain.IncidCurrentRow.last_modified_user_id = _viewModelMain.UserID;

                    if (_viewModelMain.HluTableAdapterManager.incidTableAdapter.Update(
                        (HluDataSet.incidDataTable)_viewModelMain.HluDataset.incid.GetChanges()) == -1)
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                            _viewModelMain.HluDataset.incid.TableName));
                }

                if ((_viewModelMain.IncidIhsMatrixRows != null) && _viewModelMain.IsDirtyIncidIhsMatrix())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_matrixTableAdapter.Update(
                        (HluDataSet.incid_ihs_matrixDataTable)_viewModelMain.HluDataset.incid_ihs_matrix.GetChanges()) == -1)
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                            _viewModelMain.HluDataset.incid_ihs_matrix.TableName));
                }

                if ((_viewModelMain.IncidIhsFormationRows != null) && _viewModelMain.IsDirtyIncidIhsFormation())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_formationTableAdapter.Update(
                        (HluDataSet.incid_ihs_formationDataTable)_viewModelMain.HluDataset.incid_ihs_formation.GetChanges()) == -1)
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                            _viewModelMain.HluDataset.incid_ihs_formation.TableName));
                }

                if ((_viewModelMain.IncidIhsManagementRows != null) && _viewModelMain.IsDirtyIncidIhsManagement())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_managementTableAdapter.Update(
                        (HluDataSet.incid_ihs_managementDataTable)_viewModelMain.HluDataset.incid_ihs_management.GetChanges()) == -1)
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                            _viewModelMain.HluDataset.incid_ihs_management.TableName));
                }

                if ((_viewModelMain.IncidIhsComplexRows != null) && _viewModelMain.IsDirtyIncidIhsComplex())
                {
                    if (_viewModelMain.HluTableAdapterManager.incid_ihs_complexTableAdapter.Update(
                        (HluDataSet.incid_ihs_complexDataTable)_viewModelMain.HluDataset.incid_ihs_complex.GetChanges()) == -1)
                        throw new Exception(String.Format("Failed to update '{0}' table.",
                            _viewModelMain.HluDataset.incid_ihs_complex.TableName));
                }

                if (_viewModelMain.IsDirtyIncidBap()) UpdateBap();

                if (_viewModelMain.IncidSourcesRows != null)
                {
                    int j = 0;
                    for (int i = 0; i < _viewModelMain.IncidSourcesRows.Length; i++)
                        if (_viewModelMain.IncidSourcesRows[i] != null)
                            _viewModelMain.IncidSourcesRows[i].sort_order = ++j;

                    if (_viewModelMain.HluTableAdapterManager.incid_sourcesTableAdapter.Update(
                        (HluDataSet.incid_sourcesDataTable)_viewModelMain.IncidSourcesTable.GetChanges()) == -1)
                        throw new Exception(String.Format("Failed to update {0} table.",
                            _viewModelMain.HluDataset.incid_sources.TableName));
                }

                // update all GIS rows corresponding to this incid
                List<SqlFilterCondition> incidCond = new List<SqlFilterCondition>(new SqlFilterCondition[] {
                    new SqlFilterCondition(_viewModelMain.HluDataset.incid_mm_polygons,
                        _viewModelMain.HluDataset.incid_mm_polygons.incidColumn, _viewModelMain.Incid) });

                var q = _viewModelMain.HluDataset.lut_ihs_habitat
                    .Where(r => r.code == _viewModelMain.IncidCurrentRow.ihs_habitat);
                string ihsHabitatCategory = q.Count() == 1 ? q.ElementAt(0).category : null;

                DataTable historyTable = _viewModelMain.GISApplication.UpdateFeatures(new DataColumn[] {
                    _viewModelMain.HluDataset.incid_mm_polygons.ihs_categoryColumn,
                    _viewModelMain.HluDataset.incid_mm_polygons.ihs_summaryColumn },
                    new object[] { ihsHabitatCategory, _viewModelMain.IncidIhsSummary },
                    _viewModelMain.HistoryColumns, incidCond);

                if (historyTable == null)
                    throw new Exception("Error updating GIS layer.");
                else if (historyTable.Rows.Count == 0)
                    throw new Exception("No GIS features to update.");

                // likewise update DB shadow copy of GIS layer
                if (_viewModelMain.DataBase.ExecuteNonQuery(String.Format("UPDATE {0} SET {1} = {3}, {2} = {4} WHERE {5}",
                    _viewModelMain.DataBase.QualifyTableName(_viewModelMain.HluDataset.incid_mm_polygons.TableName),
                    _viewModelMain.DataBase.QuoteIdentifier(
                        _viewModelMain.HluDataset.incid_mm_polygons.ihs_categoryColumn.ColumnName),
                    _viewModelMain.DataBase.QuoteIdentifier(
                        _viewModelMain.HluDataset.incid_mm_polygons.ihs_summaryColumn.ColumnName),
                    _viewModelMain.DataBase.QuoteValue(ihsHabitatCategory),
                    _viewModelMain.DataBase.QuoteValue(_viewModelMain.IncidIhsSummary),
                    _viewModelMain.DataBase.WhereClause(false, true, true, incidCond)),
                    _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text) == -1)
                    throw new Exception("Failed to update database copy of GIS layer.");

                // save history returned from GIS
                Dictionary<int, string> fixedValues = new Dictionary<int, string>();
                fixedValues.Add(_viewModelMain.HluDataset.history.incidColumn.Ordinal, _viewModelMain.Incid);
                ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                vmHist.HistoryWrite(fixedValues, historyTable, ViewModelWindowMain.Operations.AttributeUpdate);

                _viewModelMain.DataBase.CommitTransaction();
                _viewModelMain.HluDataset.AcceptChanges();
                _viewModelMain.Saved = true;

                _viewModelMain.IncidRowCount(true);
                _viewModelMain.IncidCurrentRowIndex = incidCurrRowIx;

                return true;
            }
            catch (Exception ex)
            {
                _viewModelMain.DataBase.RollbackTransaction();
                if (_viewModelMain.HaveGisApp)
                {
                    _viewModelMain.Saved = false;
                    MessageBox.Show("Your changes could not be saved. The error message returned was:\n\n" +
                        ex.Message, "HLU: Save Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return false;
                }
                else
                {
                    return true;
                }
            }
            finally
            {
                _viewModelMain.SavingAttempted = true;
                _viewModelMain.Saving = false;
                _viewModelMain.ChangeCursor(Cursors.Arrow, null);
            }
        }
Пример #5
0
        //---------------------------------------------------------------------
        // CHANGED: CR39 (Split and merge complete messages)
        // Return true or false success so the main class knows
        // whether to notify the user following the completion of
        // the merge.
        //
        private bool PerformPhysicalMerge()
        {
            bool success = true;

            try
            {
                HluDataSet.incid_mm_polygonsDataTable selectTable = new HluDataSet.incid_mm_polygonsDataTable();
                _viewModelMain.GetIncidMMPolygonRows(ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                                                         _viewModelMain.GisSelection.Select(), _viewModelMain.GisIDColumnOrdinals,
                                                         ViewModelWindowMain.IncidPageSize, selectTable), ref selectTable);

                if (selectTable.Count == 0)
                {
                    return(false);
                }
                else if (selectTable.Count != _viewModelMain.GisSelection.Rows.Count)
                {
                    throw new Exception(String.Format("GIS Layer and database are out of sync:\n{0} map polygons, {1} rows in table {2}.",
                                                      _viewModelMain.FragsSelectedMapCount, selectTable.Count, _viewModelMain.HluDataset.incid_mm_polygons.TableName));
                }

                // lowest toid_fragment_id in selection assigned to result feature
                string newToidFragmentID = selectTable.Min(r => r.toid_fragment_id);

                if (selectTable.GroupBy(r => r.incid).Count() == 1)
                {
                    int minFragmID = Int32.Parse(newToidFragmentID);
                    _mergeResultFeatureIndex = selectTable.Select((r, index) =>
                                                                  Int32.Parse(r.toid_fragment_id) == minFragmID ? index : -1).First(i => i != -1);
                }
                else
                {
                    _mergeFeaturesWindow       = new WindowMergeFeatures();
                    _mergeFeaturesWindow.Owner = App.Current.MainWindow;
                    _mergeFeaturesWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;

                    _mergeFeaturesViewModelPhysical = new ViewModelMergeFeatures
                                                      <HluDataSet.incid_mm_polygonsDataTable, HluDataSet.incid_mm_polygonsRow>(selectTable,
                                                                                                                               _viewModelMain.GisIDColumnOrdinals, _viewModelMain.IncidTable.incidColumn.Ordinal,
                                                                                                                               null, _viewModelMain.GISApplication);
                    _mergeFeaturesViewModelPhysical.DisplayName   = "Select Feature To Keep";
                    _mergeFeaturesViewModelPhysical.RequestClose += new ViewModelMergeFeatures
                                                                    <HluDataSet.incid_mm_polygonsDataTable, HluDataSet.incid_mm_polygonsRow>
                                                                    .RequestCloseEventHandler(_mergeFeaturesViewModelPhysical_RequestClose);

                    _mergeFeaturesWindow.DataContext = _mergeFeaturesViewModelPhysical;
                    _mergeResultFeatureIndex         = -1;

                    _mergeFeaturesWindow.ShowDialog();
                }

                if (_mergeResultFeatureIndex != -1)
                {
                    _viewModelMain.ChangeCursor(Cursors.Wait, "Processing ...");
                    bool startTransaction = _viewModelMain.DataBase.Transaction != null;

                    if (startTransaction)
                    {
                        _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);
                    }

                    try
                    {
                        _viewModelMain.ViewModelUpdate.UpdateIncidModifiedColumns(_viewModelMain.IncidsSelectedMap.ElementAt(0));

                        List <List <SqlFilterCondition> > resultFeatureWhereClause =
                            ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                                new HluDataSet.incid_mm_polygonsRow[] { selectTable[_mergeResultFeatureIndex] },
                                _viewModelMain.GisIDColumnOrdinals, ViewModelWindowMain.IncidPageSize, selectTable);

                        if (resultFeatureWhereClause.Count != 1)
                        {
                            throw new Exception("Error getting result feature from database.");
                        }

                        List <List <SqlFilterCondition> > mergeFeaturesWhereClause =
                            ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                                selectTable.Where((r, index) => index != _mergeResultFeatureIndex).ToArray(),
                                _viewModelMain.GisIDColumnOrdinals, ViewModelWindowMain.IncidPageSize, selectTable);

                        // historyTable contains rows of features merged into result feature (i.e. no longer existing)
                        // and last row with data of result feature (remaining in GIS, lowest toid_fragment_id of merged features)
                        // this last row must be removed before writing history
                        // but is needed to update geometry fields in incid_mm_polygons
                        DataTable historyTable = _viewModelMain.GISApplication.MergeFeatures(newToidFragmentID,
                                                                                             resultFeatureWhereClause[0].Select(c => c.Clone()).ToList(), _viewModelMain.HistoryColumns);

                        if (historyTable == null)
                        {
                            throw new Exception("GIS merge operation failed.");
                        }

                        DataTable resultTable = historyTable.Clone();
                        DataRow   resultRow   = historyTable.AsEnumerable().FirstOrDefault(r =>
                                                                                           r.Field <string>(_viewModelMain.HluDataset.history.toid_fragment_idColumn.ColumnName) == newToidFragmentID);
                        if (resultRow == null)
                        {
                            throw new Exception(String.Format(
                                                    "Failed to obtain geometry data of result feature from {0}.", _viewModelMain.GISApplication.ApplicationType));
                        }
                        resultTable.LoadDataRow(resultRow.ItemArray, true);
                        resultRow.Delete();
                        historyTable.AcceptChanges();

                        // synchronize DB shadow copy of GIS layer
                        MergeSynchronizeIncidMMPolygons(selectTable, resultTable, newToidFragmentID,
                                                        resultFeatureWhereClause[0], mergeFeaturesWhereClause);

                        // insert history rows (fixed values incid, toid, newToidFragmentID)
                        Dictionary <int, string> fixedValues = new Dictionary <int, string>();
                        fixedValues.Add(_viewModelMain.HluDataset.history.incidColumn.Ordinal, selectTable[0].incid);
                        fixedValues.Add(_viewModelMain.HluDataset.history.toidColumn.Ordinal, selectTable[0].toid);
                        fixedValues.Add(_viewModelMain.HluDataset.history.toid_fragment_idColumn.Ordinal, newToidFragmentID);
                        ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                        vmHist.HistoryWrite(fixedValues, historyTable, ViewModelWindowMain.Operations.PhysicalMerge);

                        if (startTransaction)
                        {
                            _viewModelMain.DataBase.CommitTransaction();
                            _viewModelMain.HluDataset.AcceptChanges();
                        }

                        // Re-count the incid records in the database.
                        _viewModelMain.IncidRowCount(true);

                        // Reset the incid and map selections but don't move
                        // to the first incid in the database.
                        _viewModelMain.ClearFilter(false);

                        // Synch with the GIS selection.
                        //---------------------------------------------------------------------
                        // FIX: 027 Force refill of Incid table after split/merge
                        // Force the Incid table to be refilled because it has been
                        // updated directly in the database rather than via the
                        // local copy.
                        _viewModelMain.RefillIncidTable = true;
                        //---------------------------------------------------------------------
                        _viewModelMain.ReadMapSelection(true);
                    }
                    catch
                    {
                        if (startTransaction)
                        {
                            _viewModelMain.DataBase.RollbackTransaction();
                        }
                        throw;
                    }
                }
            }
            catch (Exception ex)
            {
                success = false;
                MessageBox.Show("Merge operation failed. The error message returned was:\n\n" +
                                ex.Message, "HLU Merge Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally { _viewModelMain.ChangeCursor(Cursors.Arrow, null); }
            return(success);
        }
Пример #6
0
        //---------------------------------------------------------------------

        //---------------------------------------------------------------------
        // CHANGED: CR39 (Split and merge complete messages)
        // Return true or false success so the main class knows
        // whether to notify the user following the completion of
        // the merge.
        //
        private bool PerformLogicalMerge(bool physicallyMerge)
        {
            bool success = true;

            try
            {
                if (_viewModelMain.IncidsSelectedMapCount <= 0)
                {
                    return(false);
                }

                _mergeFeaturesWindow       = new WindowMergeFeatures();
                _mergeFeaturesWindow.Owner = App.Current.MainWindow;
                _mergeFeaturesWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                _mergeFeaturesWindow.MaxHeight             = App.Current.MainWindow.ActualHeight;

                HluDataSet.incidDataTable selectTable = new HluDataSet.incidDataTable();
                _viewModelMain.HluTableAdapterManager.incidTableAdapter.Fill(selectTable,
                                                                             ViewModelWindowMainHelpers.IncidSelectionToWhereClause(ViewModelWindowMain.IncidPageSize,
                                                                                                                                    _viewModelMain.IncidTable.incidColumn.Ordinal, _viewModelMain.IncidTable, _viewModelMain.IncidsSelectedMap));

                HluDataSet.incid_mm_polygonsDataTable polygons = new HluDataSet.incid_mm_polygonsDataTable();
                _viewModelMain.GetIncidMMPolygonRows(ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                                                         _viewModelMain.GisSelection.Select(), _viewModelMain.GisIDColumnOrdinals,
                                                         ViewModelWindowMain.IncidPageSize, polygons), ref polygons);

                _mergeFeaturesViewModelLogical = new ViewModelMergeFeatures <HluDataSet.incidDataTable,
                                                                             HluDataSet.incidRow>(selectTable, _viewModelMain.GisIDColumnOrdinals,
                                                                                                  _viewModelMain.IncidTable.incidColumn.Ordinal, polygons.Select(r => r).ToArray(),
                                                                                                  _viewModelMain.GISApplication);
                _mergeFeaturesViewModelLogical.DisplayName   = "Select INCID To Keep";
                _mergeFeaturesViewModelLogical.RequestClose += new ViewModelMergeFeatures <HluDataSet.incidDataTable,
                                                                                           HluDataSet.incidRow> .RequestCloseEventHandler(_mergeFeaturesViewModelLogical_RequestClose);

                _mergeFeaturesWindow.DataContext = _mergeFeaturesViewModelLogical;
                _mergeResultFeatureIndex         = -1;

                _mergeFeaturesWindow.ShowDialog();

                if (_mergeResultFeatureIndex == -1)
                {
                    return(false);
                }

                _viewModelMain.ChangeCursor(Cursors.Wait, "Processing ...");

                _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);

                try
                {
                    string keepIncid = selectTable[_mergeResultFeatureIndex].incid;

                    // assign selected incid to selected features except keepIncid
                    DataTable historyTable = _viewModelMain.GISApplication.MergeFeaturesLogically(
                        keepIncid, _viewModelMain.HistoryColumns);

                    if ((historyTable == null) || (historyTable.Rows.Count == 0))
                    {
                        throw new Exception("Failed to update GIS layer.");
                    }

                    // assign selected incid and new toid_fragment_id to selected features except keepIncid in DB shadow copy
                    string toidFragmentFormat = String.Format("D{0}",
                                                              _viewModelMain.HluDataset.incid_mm_polygons.toid_fragment_idColumn.MaxLength);

                    List <KeyValuePair <int, object> > updateFields = new List <KeyValuePair <int, object> >();
                    var keepPolygon = polygons.FirstOrDefault(r => r.incid == keepIncid);
                    if (keepPolygon != null)
                    {
                        updateFields = (from c in polygons.Columns.Cast <DataColumn>()
                                        where (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.incidColumn.Ordinal) &&
                                        (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.toidColumn.Ordinal) &&
                                        (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.toid_fragment_idColumn.Ordinal) &&
                                        (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.shape_lengthColumn.Ordinal) &&
                                        (c.Ordinal != _viewModelMain.HluDataset.incid_mm_polygons.shape_areaColumn.Ordinal)
                                        select new KeyValuePair <int, object>(c.Ordinal, keepPolygon[c.Ordinal])).ToList();
                    }

                    var updatePolygons = from r in polygons
                                         where r.incid != keepIncid
                                         orderby r.toid, r.toid_fragment_id
                    select r;

                    // update shadow DB copy of GIS layer
                    foreach (HluDataSet.incid_mm_polygonsRow r in updatePolygons)
                    {
                        r.incid = keepIncid;
                        for (int i = 0; i < updateFields.Count; i++)
                        {
                            r[updateFields[i].Key] = updateFields[i].Value;
                        }
                    }

                    if (_viewModelMain.HluTableAdapterManager.incid_mm_polygonsTableAdapter.Update(polygons) == -1)
                    {
                        throw new Exception(String.Format("Failed to update {0} table.", _viewModelMain.HluDataset.incid_mm_polygons.TableName));
                    }

                    // insert history rows (fixed value keepIncid)
                    Dictionary <int, string> fixedValues = new Dictionary <int, string>();
                    fixedValues.Add(_viewModelMain.HluDataset.history.incidColumn.Ordinal, keepIncid);
                    ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                    vmHist.HistoryWrite(fixedValues, historyTable, ViewModelWindowMain.Operations.LogicalMerge);

                    // count incid records no longer in use
                    List <string> deleteIncids = new List <string>();

                    IDataReader delReader = _viewModelMain.DataBase.ExecuteReader(String.Format(
                                                                                      "SELECT {0} FROM {1} WHERE {0} IN ({2}) GROUP BY {0} HAVING COUNT(*) = 0",
                                                                                      _viewModelMain.DataBase.QuoteIdentifier(_viewModelMain.IncidTable.incidColumn.ColumnName),
                                                                                      _viewModelMain.DataBase.QualifyTableName(_viewModelMain.IncidTable.TableName),
                                                                                      selectTable.Aggregate(new StringBuilder(), (sb, r) => sb.Append("," +
                                                                                                                                                      _viewModelMain.DataBase.QuoteValue(r.incid))).Remove(0, 1)),
                                                                                  _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text);

                    if (delReader == null)
                    {
                        throw new Exception("Error reading incid database table.");
                    }

                    while (delReader.Read())
                    {
                        deleteIncids.Add(delReader.GetString(0));
                    }
                    delReader.Close();

                    // delete any incid records no longer in use
                    if (deleteIncids.Count > 0)
                    {
                        int numAffected = _viewModelMain.DataBase.ExecuteNonQuery(String.Format(
                                                                                      "DELETE FROM {0} WHERE {1} IN ({2})",
                                                                                      _viewModelMain.DataBase.QualifyTableName(_viewModelMain.HluDataset.incid.TableName),
                                                                                      _viewModelMain.DataBase.QuoteValue(_viewModelMain.HluDataset.incid.incidColumn.ColumnName),
                                                                                      String.Join(",", deleteIncids.Select(i => _viewModelMain.DataBase.QuoteValue(i)).ToArray())),
                                                                                  _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text);

                        if (numAffected > 0)
                        {
                            _viewModelMain.IncidRowCount(true);
                        }
                    }

                    _viewModelMain.ViewModelUpdate.UpdateIncidModifiedColumns(keepIncid);

                    if (physicallyMerge && (MessageBox.Show("Perform physical merge as well?", "HLU: Physical Merge",
                                                            MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes))
                    {
                        // restore the selection
                        _viewModelMain.GisSelection.Clear();
                        foreach (HluDataSet.incid_mm_polygonsRow r in polygons)
                        {
                            DataRow newRow = _viewModelMain.GisSelection.NewRow();
                            for (int i = 0; i < _viewModelMain.GisIDColumnOrdinals.Length; i++)
                            {
                                newRow[i] = r[_viewModelMain.GisIDColumnOrdinals[i]];
                            }
                            _viewModelMain.GisSelection.Rows.Add(newRow);
                        }

                        PerformPhysicalMerge();
                    }
                    else
                    {
                        _viewModelMain.DataBase.CommitTransaction();
                        _viewModelMain.HluDataset.AcceptChanges();

                        // Re-count the incid records in the database.
                        _viewModelMain.IncidRowCount(true);

                        // Reset the incid and map selections but don't move
                        // to the first incid in the database.
                        _viewModelMain.ClearFilter(false);

                        // Synch with the GIS selection.
                        //---------------------------------------------------------------------
                        // FIX: 027 Force refill of Incid table after split/merge
                        // Force the Incid table to be refilled because it has been
                        // updated directly in the database rather than via the
                        // local copy.
                        _viewModelMain.RefillIncidTable = true;
                        //---------------------------------------------------------------------
                        _viewModelMain.ReadMapSelection(true);
                    }
                }
                catch
                {
                    _viewModelMain.DataBase.RollbackTransaction();
                    throw;
                }
            }
            catch (Exception ex)
            {
                success = false;
                MessageBox.Show("Merge operation failed. The error message returned was:\n\n" +
                                ex.Message, "HLU Merge Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally { _viewModelMain.ChangeCursor(Cursors.Arrow, null); }
            return(success);
        }
        /// <summary>
        /// Physically split features on the GIS layer.
        /// </summary>
        private bool PerformPhysicalSplit()
        {
            bool success = true;

            _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);

            try
            {
                // find next available toid_fragment_id for selected toid
                string lastToidFragmentID = _viewModelMain.RecIDs.MaxToidFragmentId(_viewModelMain.ToidsSelectedMap.ElementAt(0));

                // get a filter from the GIS selection
                List <List <SqlFilterCondition> > featuresFilter = ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                    _viewModelMain.GisSelection.AsEnumerable().Skip(1).ToArray(), _viewModelMain.GisIDColumnOrdinals,
                    ViewModelWindowMain.IncidPageSize, _viewModelMain.HluDataset.incid_mm_polygons);

                if (featuresFilter.Count != 1)
                {
                    throw new Exception("Error finding features in database.");
                }

                // update records in GIS and collect new features resulting from split
                DataTable newFeatures = _viewModelMain.GISApplication.SplitFeature(lastToidFragmentID, featuresFilter[0],
                                                                                   _viewModelMain.HluDataset.incid_mm_polygons.Columns.Cast <DataColumn>().Where(c =>
                                                                                                                                                                 c.ColumnName != _viewModelMain.HluDataset.incid_mm_polygons.shape_lengthColumn.ColumnName &&
                                                                                                                                                                 c.ColumnName != _viewModelMain.HluDataset.incid_mm_polygons.shape_areaColumn.ColumnName).ToArray());

                if ((newFeatures == null) || (newFeatures.Rows.Count < 2))
                {
                    throw new Exception("Failed to update GIS layer.");
                }

                ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                vmHist.HistoryRenameGeometryPropertyColumns(
                    _viewModelMain.HluDataset.incid_mm_polygons.shape_lengthColumn.ColumnName,
                    _viewModelMain.HluDataset.incid_mm_polygons.shape_areaColumn.ColumnName, ref newFeatures);

                // get a where clause for the original split feature
                List <List <SqlFilterCondition> > originalFeatureWhereClause = ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                    _viewModelMain.GisSelection.AsEnumerable().Take(1).ToArray(), _viewModelMain.GisIDColumnOrdinals,
                    ViewModelWindowMain.IncidPageSize, _viewModelMain.HluDataset.incid_mm_polygons);

                if (originalFeatureWhereClause.Count != 1)
                {
                    throw new Exception("Error finding features in database.");
                }

                // get the attributes of the split feature
                HluDataSet.incid_mm_polygonsDataTable updTable = new HluDataSet.incid_mm_polygonsDataTable();
                _viewModelMain.GetIncidMMPolygonRows(originalFeatureWhereClause, ref updTable);

                if ((updTable == null) || (updTable.Rows.Count != 1))
                {
                    throw new Exception("Failed to fetch incid_mm_polygon rows.");
                }

                // insert attributes of original split feature into history
                DataTable history = updTable.Copy();
                history.Columns[updTable.shape_lengthColumn.ColumnName].ColumnName = ViewModelWindowMain.HistoryGeometry1ColumnName;
                history.Columns[updTable.shape_areaColumn.ColumnName].ColumnName   = ViewModelWindowMain.HistoryGeometry2ColumnName;
                string[] historyColNames = (new string[] { ViewModelWindowMain.HistoryGeometry1ColumnName, ViewModelWindowMain.HistoryGeometry2ColumnName }
                                            .Concat(_viewModelMain.HistoryColumns.Select(c => c.ColumnName)).ToArray());
                DataColumn[] delCols = history.Columns.Cast <DataColumn>().Where(c => !historyColNames.Contains(c.ColumnName)).ToArray();
                foreach (DataColumn c in delCols)
                {
                    history.Columns.Remove(c);
                }

                vmHist.HistoryWrite(null, history, ViewModelWindowMain.Operations.PhysicalSplit);

                // update the original row
                if (_viewModelMain.DataBase.ExecuteNonQuery(String.Format("UPDATE {0} SET {1} WHERE {2}",
                                                                          _viewModelMain.DataBase.QualifyTableName(_viewModelMain.HluDataset.incid_mm_polygons.TableName),
                                                                          String.Join(",", newFeatures.Rows[0].ItemArray.Select((i, index) =>
                                                                                                                                new
                {
                    ColumnName = newFeatures.Columns[index].ColumnName,
                    value = i
                })
                                                                                      .Where(a => _viewModelMain.GisIDColumns.Count(c => c.ColumnName == a.ColumnName) == 0)
                                                                                      .Select(a => String.Format("{0} = {1}", _viewModelMain.DataBase.QuoteIdentifier(a.ColumnName),
                                                                                                                 _viewModelMain.DataBase.QuoteValue(a.value))).ToArray()),
                                                                          _viewModelMain.DataBase.WhereClause(false, true, true, originalFeatureWhereClause[0])),
                                                            _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text) == -1)
                {
                    throw new Exception("Failed to update original row in database copy of GIS layer.");
                }

                // build an insert statement for DB shadow copy of GIS layer
                string insertStatement = String.Format("INSERT INTO {0} ({1}) VALUES (",
                                                       _viewModelMain.DataBase.QualifyTableName(_viewModelMain.HluDataset.incid_mm_polygons.TableName),
                                                       String.Join(",", newFeatures.Columns.Cast <DataColumn>().Select(c =>
                                                                                                                       _viewModelMain.DataBase.QuoteIdentifier(c.ColumnName)).ToArray())) + "{0})";

                int    toidFragID = Int32.Parse(lastToidFragmentID);
                string numFormat  = String.Format("D{0}", updTable.toid_fragment_idColumn.MaxLength);

                // insert new features returned from GIS into DB shadow copy of GIS layer
                for (int i = 1; i < newFeatures.Rows.Count; i++)
                {
                    if (_viewModelMain.DataBase.ExecuteNonQuery(String.Format(insertStatement, String.Join(",",
                                                                                                           newFeatures.Rows[i].ItemArray.Select((item, index) =>
                                                                                                                                                _viewModelMain.DataBase.QuoteValue(newFeatures.Columns[index].ColumnName ==
                                                                                                                                                                                   updTable.toid_fragment_idColumn.ColumnName ?
                                                                                                                                                                                   (toidFragID + i).ToString(numFormat) : item)).ToArray())),
                                                                _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text) == -1)
                    {
                        throw new Exception("Failed to insert new rows into database copy of GIS layer.");
                    }
                }

                _viewModelMain.ViewModelUpdate.UpdateIncidModifiedColumns(_viewModelMain.IncidsSelectedMap.ElementAt(0));

                _viewModelMain.DataBase.CommitTransaction();
                _viewModelMain.HluDataset.AcceptChanges();
            }
            catch (Exception ex)
            {
                _viewModelMain.DataBase.RollbackTransaction();
                success = false;
                MessageBox.Show("Split operation failed. The error message returned was:\n\n" +
                                ex.Message, "HLU Split Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                if (success)
                {
                    _viewModelMain.IncidRowCount(true);
                    _viewModelMain.ClearFilter();
                    _viewModelMain.ReadMapSelection(true);
                }
            }
            return(success);
        }
        private bool PerformLogicalSplit()
        {
            //if ((_viewModelMain.GisSelection.Rows.Count > 1) &&
            //    (_viewModelMain.HluDataset.incid_mm_polygons.Rows.Count == _viewModelMain.GisSelection.Rows.Count))
            //{
            //    MessageBox.Show(String.Format("Cannot split: all features in map " +
            //        "selection set correspond to INCID '{0}'.", _viewModelMain.Incid), "HLU: Split",
            //        MessageBoxButton.OK, MessageBoxImage.Exclamation);
            //    return false;
            //}
            //else
            //{
            // check if selected feature is the only one pertaining to its incid
            if (_viewModelMain.GisSelection.Rows.Count == 1)
            {
                int featCount = (int)_viewModelMain.DataBase.ExecuteScalar(String.Format(
                                                                               "SELECT COUNT(*) FROM {0} WHERE {1} = {2}",
                                                                               _viewModelMain.DataBase.QualifyTableName(_viewModelMain.HluDataset.incid_mm_polygons.TableName),
                                                                               _viewModelMain.DataBase.QuoteIdentifier(_viewModelMain.HluDataset.incid_mm_polygons.incidColumn.ColumnName),
                                                                               _viewModelMain.DataBase.QuoteValue(_viewModelMain.Incid)),
                                                                           _viewModelMain.DataBase.Connection.ConnectionTimeout, CommandType.Text);
                if (featCount == 1)
                {
                    MessageBox.Show(String.Format("Cannot split: feature selected in map is the only" +
                                                  " feature corresponding to INCID {0}", _viewModelMain.Incid), "HLU: Split",
                                    MessageBoxButton.OK, MessageBoxImage.Asterisk);
                    return(false);
                }
            }

            bool success = true;

            _viewModelMain.DataBase.BeginTransaction(true, IsolationLevel.ReadCommitted);

            try
            {
                _viewModelMain.ViewModelUpdate.UpdateIncidModifiedColumns(_viewModelMain.CurrentIncid);

                // create new incid by cloning the current one
                string msg;
                if (!CloneCurrentIncid(false, out msg))
                {
                    throw new Exception(msg);
                }
                string newIncid = _viewModelMain.RecIDs.CurrentIncid;

                // update GIS layer
                DataTable historyTable = _viewModelMain.GISApplication.SplitFeaturesLogically(newIncid,
                                                                                              _viewModelMain.HistoryColumns.Concat(new DataColumn[] { new DataColumn(
                                                                                                                                                          _viewModelMain.HluDataset.history.modified_toid_fragment_idColumn.ColumnName.Replace(
                                                                                                                                                              _viewModelMain.HluDataset.incid_mm_polygons.toid_fragment_idColumn.ColumnName, String.Empty) +
                                                                                                                                                          GISApplication.GISApp.HistoryAdditionalFieldsDelimiter +
                                                                                                                                                          _viewModelMain.HluDataset.incid_mm_polygons.toid_fragment_idColumn.ColumnName,
                                                                                                                                                          _viewModelMain.HluDataset.history.modified_toid_fragment_idColumn.DataType) }).ToArray());
                if (historyTable == null)
                {
                    throw new Exception("Failed to update GIS layer.");
                }

                // update DB shadow copy of GIS layer
                HluDataSet.incid_mm_polygonsDataTable polygons = new HluDataSet.incid_mm_polygonsDataTable();
                _viewModelMain.GetIncidMMPolygonRows(ViewModelWindowMainHelpers.GisSelectionToWhereClause(
                                                         _viewModelMain.GisSelection.Select(), _viewModelMain.GisIDColumnOrdinals,
                                                         ViewModelWindowMain.IncidPageSize, polygons), ref polygons);

                historyTable.PrimaryKey = historyTable.Columns.Cast <DataColumn>()
                                          .Where(c => _viewModelMain.GisIDColumnOrdinals.Contains(c.Ordinal)).ToArray();

                foreach (HluDataSet.incid_mm_polygonsRow r in polygons)
                {
                    DataRow historyRow = historyTable.Rows.Find(r.ItemArray.Where((i, index) =>
                                                                                  _viewModelMain.GisIDColumnOrdinals.Contains(index)).ToArray());
                    r.toid_fragment_id = historyRow.Field <string>(
                        _viewModelMain.HluDataset.history.modified_toid_fragment_idColumn.ColumnName);
                    r.incid = newIncid;
                }
                if (_viewModelMain.HluTableAdapterManager.incid_mm_polygonsTableAdapter.Update(polygons) == -1)
                {
                    throw new Exception(String.Format("Failed to update {0} table.", _viewModelMain.HluDataset.incid_mm_polygons.TableName));
                }

                _viewModelMain.ViewModelUpdate.UpdateIncidModifiedColumns(
                    historyTable.Rows[0][_viewModelMain.HluDataset.history.incidColumn.ColumnName].ToString());

                // write history
                Dictionary <int, string> fixedValues = new Dictionary <int, string>();
                fixedValues.Add(_viewModelMain.HluDataset.history.incidColumn.Ordinal, newIncid);
                historyTable.Columns[_viewModelMain.HluDataset.history.incidColumn.ColumnName].ColumnName =
                    _viewModelMain.HluDataset.history.modified_incidColumn.ColumnName;
                ViewModelWindowMainHistory vmHist = new ViewModelWindowMainHistory(_viewModelMain);
                vmHist.HistoryWrite(fixedValues, historyTable, ViewModelWindowMain.Operations.LogicalSplit);

                _viewModelMain.DataBase.CommitTransaction();
                _viewModelMain.HluDataset.AcceptChanges();
            }
            catch (Exception ex)
            {
                _viewModelMain.DataBase.RollbackTransaction();
                success = false;
                MessageBox.Show("Split operation failed. The error message returned was:\n\n" +
                                ex.Message, "HLU Split Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                if (success)
                {
                    _viewModelMain.ClearFilter();

                    // re-count records
                    _viewModelMain.IncidRowCount(true);

                    // synch with GIS selection
                    _viewModelMain.ReadMapSelection(true);
                }
            }
            //}
            return(success);
        }