如果我这样做:
RelatedLink newLink = new RelatedLink(linkTypeEnd, id);
if (workItem.Links.Contains(newLink)) return;
workItem.Links.Add(newLink);
它仍然在使用ValidationException的Add方法崩溃,声明链接已经在集合中。
TF237099:重复的工作项链接。
那么Contains真正检查的是什么?参考平等?肯定不是吗?
任何人都有关于如何处理这个问题的一些提示?我正在编写一个工具,用于将需求从一个众所周知的工具迁移到TFS。
答案 0 :(得分:3)
所以你有一个给定的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()它做了什么?” - &GT;我有没有的答案 我希望你能以某种方式使用我上面实现的内容。
答案 1 :(得分:3)
看起来TFS 2013的行为也没有改变。我遇到了完全相同的问题,这就是我在拆卸工具和运气方面的帮助。
每种类型的链接都以自己的方式实现Equals
方法。据我所知,它是内部字段的组合,它唯一地标识链接对象。对于Hyperlink,它只是重要的目标路径。
RelatedLink
在这里很特别。首先,它的Equals
方法比较了几个内部字段,特别是源ID和目标ID。
当您刚刚创建了RelatedLink
对象时,它的目标ID指向null
。它是有道理的 - 你没有添加一个工作项的链接,它不知道它与它有什么关系。
现在,在代码的第二行,您调用Contains
方法,然后返回false
。对于新创建的链接始终false
!这是因为Contains
方法实现了调用Equals
方法的方法,该方法通过源ID和目标ID比较相关链接。但对于刚刚创建的相关链接,目标ID始终为null
。另一方面,workItem.Links
集合中每个对象的目标ID永远不会是null
。
因此,Contains
方法在这种情况下是无用的。我最终得到了一个丑陋的解决方法,但至少它不需要使用ID维护外部集合:
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的其他人:)