WorkItem.Links.Contains () что он делает? - PullRequest
2 голосов
/ 20 октября 2011

Если я это сделаю:

RelatedLink newLink = new RelatedLink(linkTypeEnd, id);
if (workItem.Links.Contains(newLink)) return;
workItem.Links.Add(newLink);

Он по-прежнему падает на методе Add с ValidationException, заявляя, что ссылка уже находится в коллекции.

TF237099: Двойная ссылка на рабочий элемент.

Так что же на самом деле проверяет Contains?эталонное равенство?конечно нет?

Кто-нибудь получил несколько советов о том, как справиться с этим?Я пишу инструмент для переноса требований из хорошо известного инструмента в TFS.

Ответы [ 2 ]

3 голосов
/ 01 ноября 2014

Похоже, что поведение не изменилось и для TFS 2013. Я столкнулся с точно такой же проблемой, и это то, что я нашел с помощью инструмента разборки и немного удачи.

Каждый тип ссылки реализует метод Equals по-своему. Насколько я могу судить, это комбинация внутренних полей, которая однозначно идентифицирует объект ссылки. Для Гиперссылки важен только целевой путь.

* * * * * RelatedLink здесь особенный. Прежде всего, его метод Equals сравнивает несколько внутренних полей, в частности, идентификатор источника и идентификатор цели.

Когда вы только что создали объект RelatedLink, его целевой идентификатор указывает на null. И это имеет смысл - вы не добавили ссылку на рабочий элемент и не знаете, с чем это связано.

Теперь во второй строке вашего кода вы вызываете метод Contains, и он возвращает false. Всегда false для вновь созданной ссылки! Это связано с тем, что в методе Contains реализован способ вызова метода Equals, который сравнивает связанные ссылки по идентификатору источника и идентификатору цели. Но идентификатор цели ВСЕГДА null для связанной ссылки, которая только что создана. С другой стороны, целевой идентификатор каждого отдельного объекта в коллекции workItem.Links никогда не равен null.

Следовательно, метод Contains в этом случае бесполезен. В итоге я нашел уродливый обходной путь, но, по крайней мере, он не требует поддержки внешней коллекции с идентификаторами:

RelatedLink newLink = new RelatedLink(linkTypeEnd, id);

if (workItem.Links.Cast<Link>().FirstOrDefault(l => l.GetType() == typeof(RelatedLink) && ((RelatedLink)l).RelatedWorkItemId == relatedLink.RelatedWorkItemId) == null) 
//if (workItem.Links.Contains(newLink)) 
  return;
workItem.Links.Add(newLink);

Итак, вместо того, чтобы полагаться на метод Contains, я проверяю данные, которые могут быть идентичными и могут привести к явной ошибке duplicate relation.

P.S. Я понимаю, что получение ответа через 3 года не имеет значения. Надеемся, что это может помочь другим, кто переносит рабочие элементы из «хорошо известных систем» в TFS:)

3 голосов
/ 24 октября 2011

Итак, у вас есть данный WorkItem (предположим, с ID = 1000), и вы хотите добавить к нему связанный WorkItem (предположим, с ID = 1001).
Просто перейдем к

workItem.Links.Add(newLink);

не будет работать, поскольку выдает исключение, которое вы предоставили в случае, если WI 1001 уже является ссылкой на WI 1000.

Поэтому перед добавлением необходимо проверить, находится ли WI 1001 в ссылках 1000,Это было возможно следующим образом:

WorkItem workItem = workItemStore.GetWorkItem(1000);  

LinkCollection links = workItem.Links;
List<int> relatedWorkItemIds = new List<int>();
foreach (var link in links)
{
   relatedWorkItemIds.Add(((Microsoft.TeamFoundation.WorkItemTracking.Client.RelatedLink) (link)).RelatedWorkItemId);
}

if(relatedWorkItemIds.Contains(1001))
{
   return;
}
else
{
   WorkItemLinkTypeEnd linkTypeEnd = workItemStore.WorkItemLinkTypes.LinkTypeEnds["Child"]; 
   RelatedLink newLink = new RelatedLink(linkTypeEnd, 1001);
   workItem.Links.Add(newLink);
}

Работая над ответом, я понял, что вы прямо спрашиваете "WorkItem.Links.Contains (), что он делает?"-> У меня есть нет ответа.
Я надеюсь, что вы сможете каким-то образом использовать то, что я реализовал выше.

...