private bool ProcessWorkItemWithLogging(WorkItemData sourceWorkItemData, int current, int totalWorkItem)
        {
            var sourceWorkItem = TfsExtensions.ToWorkItem(sourceWorkItemData);

            workItemLog = contextLog.ForContext("SourceWorkItemId", sourceWorkItem.Id);

            using (LogContext.PushProperty("sourceWorkItemTypeName", sourceWorkItem.Type.Name))
                using (LogContext.PushProperty("currentWorkItem", current))
                    using (LogContext.PushProperty("totalWorkItems", totalWorkItem))
                        using (LogContext.PushProperty("sourceWorkItemId", sourceWorkItem.Id))
                            using (LogContext.PushProperty("sourceRevisionInt", sourceWorkItem.Revision))
                                using (LogContext.PushProperty("targetWorkItemId", null))
                                {
                                    ProcessWorkItem(sourceWorkItemData, _config.WorkItemCreateRetryLimit);
                                    if (_config.PauseAfterEachWorkItem)
                                    {
                                        Console.WriteLine("Do you want to continue? (y/n)");
                                        if (Console.ReadKey().Key != ConsoleKey.Y)
                                        {
                                            workItemLog.Warning("USER ABORTED");
                                            return(false);
                                        }
                                    }
                                }
            return(true);
        }
        protected override void InternalExecute()
        {
            Log.LogInformation("WorkItemMigrationContext::InternalExecute ");
            if (_config == null)
            {
                throw new Exception("You must call Configure() first");
            }
            var workItemServer = Engine.Source.GetService <WorkItemServer>();

            attachmentEnricher    = new TfsAttachmentEnricher(workItemServer, _config.AttachmentWorkingPath, _config.AttachmentMaxSize);
            workItemLinkEnricher  = Services.GetRequiredService <TfsWorkItemLinkEnricher>();
            embededImagesEnricher = Services.GetRequiredService <TfsEmbededImagesEnricher>();
            gitRepositoryEnricher = Services.GetRequiredService <TfsGitRepositoryEnricher>();
            nodeStructureEnricher = Services.GetRequiredService <TfsNodeStructureEnricher>();
            _witClient            = new WorkItemTrackingHttpClient(Engine.Target.Config.AsTeamProjectConfig().Collection, Engine.Target.Credentials);
            //Validation: make sure that the ReflectedWorkItemId field name specified in the config exists in the target process, preferably on each work item type.
            PopulateIgnoreList();

            Log.LogInformation("Migrating all Nodes before the work item run.");
            nodeStructureEnricher.MigrateAllNodeStructures(_config.PrefixProjectToNodes, _config.NodeBasePaths);

            var stopwatch = Stopwatch.StartNew();
            //////////////////////////////////////////////////
            string sourceQuery =
                string.Format(
                    @"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY {1}",
                    _config.WIQLQueryBit, _config.WIQLOrderBit);

            // Inform the user that he maybe has to be patient now
            contextLog.Information("Querying items to be migrated: {SourceQuery} ...", sourceQuery);
            var sourceWorkItems = Engine.Source.WorkItems.GetWorkItems(sourceQuery);

            contextLog.Information("Replay all revisions of {sourceWorkItemsCount} work items?", sourceWorkItems.Count);
            //////////////////////////////////////////////////
            contextLog.Information("Found target project as {@destProject}", Engine.Target.WorkItems.Project.Name);
            //////////////////////////////////////////////////////////FilterCompletedByQuery
            if (_config.FilterWorkItemsThatAlreadyExistInTarget)
            {
                contextLog.Information("[FilterWorkItemsThatAlreadyExistInTarget] is enabled. Searching for work items that have already been migrated to the target...", sourceWorkItems.Count());
                sourceWorkItems = ((TfsWorkItemMigrationClient)Engine.Target.WorkItems).FilterExistingWorkItems(sourceWorkItems, new TfsWiqlDefinition()
                {
                    OrderBit = _config.WIQLOrderBit, QueryBit = _config.WIQLQueryBit
                }, (TfsWorkItemMigrationClient)Engine.Source.WorkItems);
                contextLog.Information("!! After removing all found work items there are {SourceWorkItemCount} remaining to be migrated.", sourceWorkItems.Count());
            }
            //////////////////////////////////////////////////

            var result = validateConfig.ValidatingRequiredField(Engine.Target.Config.AsTeamProjectConfig().ReflectedWorkItemIDFieldName, sourceWorkItems);

            if (!result)
            {
                var ex = new InvalidFieldValueException("Not all work items in scope contain a valid ReflectedWorkItemId Field!");
                Log.LogError(ex, "Not all work items in scope contain a valid ReflectedWorkItemId Field!");
                throw ex;
            }
            //////////////////////////////////////////////////
            _current       = 1;
            _count         = sourceWorkItems.Count;
            _elapsedms     = 0;
            _totalWorkItem = sourceWorkItems.Count;
            foreach (MigrationTools._EngineV1.DataContracts.WorkItemData sourceWorkItemData in sourceWorkItems)
            {
                var sourceWorkItem = TfsExtensions.ToWorkItem(sourceWorkItemData);
                workItemLog = contextLog.ForContext("SourceWorkItemId", sourceWorkItem.Id);
                using (LogContext.PushProperty("sourceWorkItemTypeName", sourceWorkItem.Type.Name))
                    using (LogContext.PushProperty("currentWorkItem", _current))
                        using (LogContext.PushProperty("totalWorkItems", _totalWorkItem))
                            using (LogContext.PushProperty("sourceWorkItemId", sourceWorkItem.Id))
                                using (LogContext.PushProperty("sourceRevisionInt", sourceWorkItem.Revision))
                                    using (LogContext.PushProperty("targetWorkItemId", null))
                                    {
                                        ProcessWorkItem(sourceWorkItemData, _config.WorkItemCreateRetryLimit);
                                        if (_config.PauseAfterEachWorkItem)
                                        {
                                            Console.WriteLine("Do you want to continue? (y/n)");
                                            if (Console.ReadKey().Key != ConsoleKey.Y)
                                            {
                                                workItemLog.Warning("USER ABORTED");
                                                break;
                                            }
                                        }
                                    }
            }
            //////////////////////////////////////////////////
            stopwatch.Stop();

            contextLog.Information("DONE in {Elapsed}", stopwatch.Elapsed.ToString("c"));
        }
        protected override void InternalExecute()
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            //////////////////////////////////////////////////
            IWorkItemQueryBuilder wiqb = Services.GetRequiredService <IWorkItemQueryBuilder>();
            //Builds the constraint part of the query
            string constraints = BuildQueryBitConstraints();

            wiqb.Query = string.Format(@"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY [System.Id] ", constraints);

            List <MigrationTools._EngineV1.DataContracts.WorkItemData> sourceWIS = Engine.Target.WorkItems.GetWorkItems((IWorkItemQueryBuilder)wiqb);

            Log.LogInformation("Migrate {0} work items?", sourceWIS.Count);
            //////////////////////////////////////////////////
            ProjectData destProject = Engine.Target.WorkItems.GetProject();

            Log.LogInformation("Found target project as {0}", destProject.Name);

            int  current   = sourceWIS.Count;
            int  count     = 0;
            long elapsedms = 0;

            foreach (MigrationTools._EngineV1.DataContracts.WorkItemData sourceWI in sourceWIS)
            {
                Stopwatch witstopwatch = Stopwatch.StartNew();
                MigrationTools._EngineV1.DataContracts.WorkItemData targetFound;
                targetFound = Engine.Target.WorkItems.FindReflectedWorkItem((MigrationTools._EngineV1.DataContracts.WorkItemData)sourceWI, (bool)false);
                Log.LogInformation("{0} - Updating: {1}-{2}", current, sourceWI.Id, sourceWI.Type);
                if (targetFound == null)
                {
                    Log.LogWarning("{0} - WARNING: does not exist {1}-{2}", current, sourceWI.Id, sourceWI.Type);
                }
                else
                {
                    Log.LogInformation("...Exists");
                    TfsExtensions.ToWorkItem(targetFound).Open();
                    Engine.FieldMaps.ApplyFieldMappings(sourceWI, targetFound);
                    if (TfsExtensions.ToWorkItem(targetFound).IsDirty)
                    {
                        try
                        {
                            TfsExtensions.SaveToAzureDevOps(targetFound);
                            Log.LogInformation("          Updated");
                        }
                        catch (ValidationException ve)
                        {
                            Log.LogError(ve, "          [FAILED] {0}", ve.ToString());
                        }
                    }
                    else
                    {
                        Log.LogInformation("          No changes");
                    }
                    TfsExtensions.ToWorkItem(sourceWI).Close();
                }
                witstopwatch.Stop();
                elapsedms = elapsedms + witstopwatch.ElapsedMilliseconds;
                current--;
                count++;
                TimeSpan average   = new TimeSpan(0, 0, 0, 0, (int)(elapsedms / count));
                TimeSpan remaining = new TimeSpan(0, 0, 0, 0, (int)(average.TotalMilliseconds * current));
                Log.LogInformation("Average time of {0} per work item and {1} estimated to completion", string.Format(@"{0:s\:fff} seconds", average), string.Format(@"{0:%h} hours {0:%m} minutes {0:s\:fff} seconds", remaining));
            }
            //////////////////////////////////////////////////
            stopwatch.Stop();
            Log.LogInformation("DONE in {Elapsed}", stopwatch.Elapsed.ToString("c"));
        }