private void UpdateRelatedRecords()
        {
            WorkAsync("Updating Related Records...",
                (w, e) => // Work To Do Asynchronously
                {
                    w.ReportProgress(0, "Parsing Selected Surviving Record");

                    // Uncheck Selected Record from the To Be Deleted List
                    var formReader = new FormEntryReader(null);
                    var selectedEntityRecordFromStep5 = formReader.GetSelectedRowItem(entityRecordGrid);
                    selectedEntityRecordFromStep5["Mark for Deletion"] = false;
                    entityRecordGrid.Refresh();

                    // Get RelatedEntityValues
                    var entitySelected = formReader.ReadEntitySelected(entityDropdown);
                    formReader.ReadRelatedEntitySelected(relationShipDropdown);
                    var relatedEntityPkName = formReader.ReferencingEntityName + "id";
                    var relatedEntity = formReader.ReferencingEntityName;
                    var linkColumnOnRelatedEntity = formReader.ReferencingAttributeName;

                    var formUpdater = new GridUpdater(relatedEntityGrid);
                    formUpdater.Where(row => row[relatedEntityPkName] is Guid)
                        .ForEach(row =>
                        {
                            var currentRow = row.Table.Rows.IndexOf(row) + 1;
                            // TO DO: The indexing totals system can be improved to cover actual work rows
                            var totalRows = row.Table.Rows.Count;
                            w.ReportProgress(currentRow / totalRows, "Updating Row ID: " + currentRow);
                            var updateItem = new Entity(relatedEntity) {Id = (Guid) row[relatedEntityPkName]};
                            updateItem[linkColumnOnRelatedEntity] = new EntityReference(
                                entitySelected,
                                (Guid)selectedEntityRecordFromStep5[entitySelected + "id"]);
                            Service.Update(updateItem);
                            row["Updated"] = true;
                        });
                    w.ReportProgress(99, "Finishing");
                    formUpdater.Refresh();

                    e.Result = "Update Complete";
                },
                e => // Finished Async Call.  Cleanup
                    MessageBox.Show(e.Result as string),
                e => // Logic wants to display an update.  This gets called when ReportProgress Gets Called
                    SetWorkingMessage(e.UserState.ToString()));
        }
        private void QueryRelatedRecords()
        {
            WorkAsync("Querying Related Entities for Selected Row from Step 4",
                e => // Work To Do Asynchronously
                {
                    var fetchXmlBuilder = new RelatedEntityQueryBuilder();
                    var formEntryReader = new FormEntryReader(fetchXmlBuilder);
                    formEntryReader.ReadEntitySelected(entityDropdown);
                    formEntryReader.ReadUniqueIdentifierAttributes(entityAttributeView);
                    formEntryReader.ReadFilterValuesFromSelectedRow(duplicatesGrid);
                    formEntryReader.ReadRelatedEntitySelected(relationShipDropdown);
                    fetchXmlBuilder.AddColumn(new CrmEntityAttribute("createdon", "DateTime"));
                    var response = GetRecordsFromCrm(fetchXmlBuilder.GetOutput());

                    var reader = new FetchXmlResponseReader(response);
                    var dataset = reader.ParseRelatedRecords(fetchXmlBuilder);
                    SafeSetDataSource(relatedEntityGrid, dataset);

                    e.Result = "Step 6 Record View Updated";
                }, e =>
                {
                    MessageBox.Show(e.Result as string);
                });
        }
        private void QueryRecords()
        {
            WorkAsync("Querying Records for Selected Rows from Step 4",
                e => // Work To Do Asynchronously
                {
                    var fetchXmlBuilder = new EntityQueryBuilder();
                    var formEntryReader = new FormEntryReader(fetchXmlBuilder);
                    formEntryReader.ReadEntitySelected(entityDropdown);
                    formEntryReader.ReadUniqueIdentifierAttributes(entityAttributeView);
                    formEntryReader.ReadFilterValuesFromSelectedRow(duplicatesGrid);
                    formEntryReader.ReadDisplayAttributes(entityAttributeView);
                    var response = GetRecordsFromCrm(fetchXmlBuilder.GetOutput());

                    var reader = new FetchXmlResponseReader(response);
                    var dataset = reader.ParseEntityQueryResponse(fetchXmlBuilder);
                    SafeSetDataSource(entityRecordGrid, dataset);

                    e.Result = "Step 5 Record View Updated";
                }, e => MessageBox.Show(e.Result as string));
        }
        private void QueryDuplicates()
        {
            WorkAsync(
                string.Format("Querying Duplicates [Entity:{0} - Attributes Selected:{1}", entityDropdown.SelectedValue,
                    entityAttributeView.RowCount),
                e => // Work To Do Asynchronously
                {
                    var fetchXmlBuilder = new DuplicateQueryBuilder();
                    var formEntryReader = new FormEntryReader(fetchXmlBuilder);
                    formEntryReader.ReadEntitySelected(entityDropdown);
                    formEntryReader.ReadUniqueIdentifierAttributes(entityAttributeView);
                    fetchXmlBuilder.AddCustomFilterXml(customXMLFilterBox.Text);
                    e.Result = GetRecordsFromCrm(fetchXmlBuilder.GetOutput());

                },
                e => // Cleanup when work has completed
                {
                    var reader = new FetchXmlResponseReader(e.Result as EntityCollection);

                    var fetchXmlBuilder = new DuplicateQueryBuilder();
                    var formEntryReader = new FormEntryReader(fetchXmlBuilder);
                    formEntryReader.ReadEntitySelected(entityDropdown);
                    formEntryReader.ReadUniqueIdentifierAttributes(entityAttributeView);
                    fetchXmlBuilder.AddCustomFilterXml(customXMLFilterBox.Text);
                    var dataSet = reader.ParseGroupByResponse(fetchXmlBuilder);
                    SafeSetDataSource(duplicatesGrid, dataSet);
                });
        }
 private void Output_Debug(object sender, EventArgs e)
 {
     var fetchXmlBuilder = new DuplicateQueryBuilder();
     var formEntryReader = new FormEntryReader(fetchXmlBuilder);
     formEntryReader.ReadEntitySelected(entityDropdown);
     formEntryReader.ReadUniqueIdentifierAttributes(entityAttributeView);
     fetchXmlBuilder.AddCustomFilterXml(customXMLFilterBox.Text);
     var query = fetchXmlBuilder.GetOutput().Query;
     MessageBox.Show(string.Format("Hit CTRL - C to copy the query below: {0}", query));
 }
        private void DeleteMarkedRecords()
        {
            WorkAsync("Deleting Marked Records...",
                (w, e) => // Work To Do Asynchronously
                {
                    var formReader = new FormEntryReader(null);
                    var entitySelected = formReader.ReadEntitySelected(entityDropdown);

                    w.ReportProgress(0, "Start Parsing");
                    var formUpdater = new GridUpdater(entityRecordGrid);
                    formUpdater.Where(row => (bool) row["Mark for Deletion"])
                        .ForEach(row =>
                        {
                            var currentRow = row.Table.Rows.IndexOf(row) + 1;
                            // TO DO: The indexing totals system can be improved to cover actual work rows
                            var totalRows = row.Table.Rows.Count;
                            w.ReportProgress(currentRow / totalRows, "Deleting Row ID: " + currentRow);
                            Service.Delete(entitySelected, (Guid)row[entitySelected+"id"]);
                        });
                    w.ReportProgress(99, "Finishing");
                    formUpdater.Refresh();

                    // Populate whatever the results that need to be returned to the Results Property
                    e.Result = "Deletion Complete";
                },
                e => // Finished Async Call.  Cleanup
                    MessageBox.Show(e.Result as string),
                e => // Logic wants to display an update.  This gets called when ReportProgress Gets Called
                    SetWorkingMessage(e.UserState.ToString()));
        }