private async Task MigrateWorkItemRelationsAsync(MigrationContext context, IEnumerable <WorkItemRelation> relations, WorkItem targetItem, CancellationToken cancellationToken) { var doc = new JsonPatchDocument(); foreach (var relation in relations) { var isChild = relation.IsChild(); var isParent = !isChild && relation.IsParent(); var isRelated = !isChild && !isParent && relation.IsRelated(); //Not a relation we care about if (!isChild && !isParent && !isRelated) { continue; } //Get the related item information var relatedId = relation.GetRelatedId(); if (relatedId <= 0) { continue; } var related = context.GetMigratedWorkItem(relatedId); if (isChild) { //If the child has been migrated then add a child link to the related item //else if the target isn't closed (or the override setting is set) then add the related item to migration list if (related != null) { if (related.TargetId != 0) { Logger.Debug($"Adding Child link to {related.TargetId}"); doc.AddLink(WorkItemRelations.Child, related.TargetUrl); } else { Logger.Warning($"Skipping Child link to {related.SourceId} because it failed to migrate"); } } else if (!targetItem.IsClosed() || Settings.IncludeChildLinksOnClosed) { Logger.Debug($"Adding Child link {relatedId} to migration list"); AddToMigrationQueue(context.MigrationQueue, new MigratedWorkItem() { SourceId = relatedId }); } ; } else if (isParent) { //If the parent has already been migrated then add a parent link to the related item if (related != null) { if (related.TargetId != 0) { Logger.Debug($"Adding Parent link to {related.TargetId}"); doc.AddLink(WorkItemRelations.Parent, related.TargetUrl); } else { Logger.Warning($"Skipping Parent link to {related.SourceId} because it failed to migrate"); } } else if (!targetItem.IsClosed() || Settings.IncludeParentLinksOnClosed) { Logger.Debug($"Adding Parent link {relatedId} to migration list"); AddToMigrationQueue(context.MigrationQueue, new MigratedWorkItem() { SourceId = relatedId }); } ; } else if (isRelated) { //If the related item has already been migrated then add a related link to it //else if the target is not closed (or the override setting is set) then add the related item to the migration list if (related != null) { if (related.TargetId != 0) { Logger.Debug($"Adding Related link to {related.TargetId}"); doc.AddLink(WorkItemRelations.Related, related.TargetUrl); } else { Logger.Warning($"Skipping Related link to {related.SourceId} because it failed to migrate"); } } else if (!targetItem.IsClosed() || Settings.IncludeRelatedLinksOnClosed) { Logger.Debug($"Adding Related link {relatedId} to migration list"); AddToMigrationQueue(context.MigrationQueue, new MigratedWorkItem() { SourceId = relatedId }); } ; } ; //else ignore cancellationToken.ThrowIfCancellationRequested(); } ; //If we have made any changes then update the target if (doc.Any()) { await context.TargetService.UpdateWorkItemUnrestrictedAsync(targetItem, doc, cancellationToken).ConfigureAwait(false); } }