Querying on WorkItem Links through the API
In Rosario Team Foundation Server, significant new functionality is added for liking work item types
https://blogs.msdn.com/bharry/archive/2007/08/06/work-item-tracking-enhancements-in-the-aug-rosario-ctp.aspx
https://blogs.msdn.com/teams_wit_tools/archive/tags/Rosario/default.aspx
Here, I will try to describe how to query on link through the work item API.
First let’s get a list of work item types in the server.
After the obligatory logging in into the TFS and getting the Work Item Store, you need to go to a
specific project and then get the work item types defined for that project. Here is a code snippet
that prints all the work item types in a project
TeamFoundationServer TFS; WorkItemStore WIStore; TFS = TeamFoundationServerFactory.GetServer(https://"<your tfs server>:<port typically = 8080>"); WIStore = TFS.GetService(typeof(WorkItemStore)) as WorkItemStore; Project TeamProject = WIStore.Projects["MyProject"]; WorkItemTypeCollection workItemTypes = TeamProject.WorkItemTypes; foreach (WorkItemType workItemType in workItemTypes) { Console.WriteLine(workItemType.Name); } |
Now that we know how to get the work item types, we can look at the work item link types
While the work item types are project specific, work item link types are global to all projects.
The code snippet below shows how to get the work item link types.
WorkItemLinkTypeCollection worItemLinkTypes = WIStore.WorkItemLinkTypes; foreach (WorkItemLinkType workItemLinkType in worItemLinkTypes) { Console.WriteLine("-----------------------------------------"); Console.WriteLine("Base ReferenceName: {0}", workItemLinkType.BaseReferenceName); Console.WriteLine("Id: {0}", workItemLinkType.Id); Console.WriteLine("Name: {0}", workItemLinkType.Name); Console.WriteLine("IsDirectional: {0}", workItemLinkType.IsDirectional); Console.WriteLine("IsForwardLink: {0}", workItemLinkType.IsForwardLink); Console.WriteLine("IsNonCircular: {0}", workItemLinkType.IsNonCircular); Console.WriteLine("IsOneToMany: {0}", workItemLinkType.IsOneToMany); Console.WriteLine("LinkTopology: {0}", workItemLinkType.LinkTopology.ToString()); WorkItemLinkType workItemLinkTypeReverse = workItemLinkType.Reverse; Console.WriteLine("\t...."); Console.WriteLine("\tId: {0}", workItemLinkTypeReverse.Id); Console.WriteLine("\tName: {0}", workItemLinkTypeReverse.Name); Console.WriteLine("\tIsDirectional: {0}", workItemLinkTypeReverse.IsDirectional); Console.WriteLine("\tIsForwardLink: {0}", workItemLinkTypeReverse.IsForwardLink); Console.WriteLine("\tIsNonCircular: {0}", workItemLinkTypeReverse.IsNonCircular); Console.WriteLine("\tIsOneToMany: {0}", workItemLinkTypeReverse.IsOneToMany); Console.WriteLine("\tLinkTopology: {0}", workItemLinkTypeReverse.LinkTopology.ToString()); } |
When you run the code it prints something like
Base ReferenceName: Microsoft.VSTS.Common.Produces
Id: 4
Name: Produces
IsDirectional: True
IsForwardLink: True
IsNonCircular: True
IsOneToMany: False
....
Id: -4
Name: Is Produced By
IsDirectional: True
IsForwardLink: False
IsNonCircular: True
IsOneToMany: False
So it seems that a “Relation” is represented by two “Work Item Link Type” instances. Each direction of the “relation” is a work item link type. The other direction is the “reverse” work item link type.
Let’s take a concrete example:
A feature is produced by one or more deliverables. A deliverable produces one or more features.
This relation is a many to many relation. This relation has a BaseReferenceName – “Produces” and is represented by two work item link type instances.
Features Is Produced by Deliverable
Deliverable Produces Feature.
Each work item link type has a “Reverse” property that points to its counterpart.
Once I got the work item types and work item link types, I tried to see if there are constraints on what link types a work item type can have. For example, can a feature have a parent as a deliverable?
Can a deliverable have a parent Task? It seems that given a set of work item types, only certain relations are valid for a work item of a give type. Unfortunately, as of now, this feature is not implemented.
So any work item type can have any relation or link type as you desire. The team foundation server team is apparently thinking about adding this in the subsequent CTP releases, but nothing is guaranteed.
Querying on Links
Let’s take a look at how to query the work item links.
The WorkItemLinks property will give you all the work item links. Since there could be other types of links, the BaseLinkType property is looked at to make sure that this is the work item link. By querying the WorkItemLink.SourceId and TargetId properties, you can discover what the work item is on the other side of the relation. In this case, my feature 9999, is hooked up to a deliverable via a “Produces” relation
and with a “Is Produced By “directional link.
WorkItem wiFeatureGroup = WIStore.GetWorkItem(9999); foreach (WorkItemLink wiLink in wiFeatureGroup.WorkItemLinks) { if (wiLink.BaseType == BaseLinkType.WorkItemLink) { if(wiLink.LinkType.BaseReferenceName == "Microsoft.VSTS.Common.Produces" && wiLink.LinkType.Name == "Is Produced By") { WorkItem wiDeliverable = WIStore.GetWorkItem(wiLink.TargetId); Console.WriteLine("The target WorkItemID is {0} and its type is {1}", wiDeliverable.Id, wiDeliverable.Type.Name); } } } |
Adding a link
Adding a link is simple. You create a link and add it to the collection, then save the work item
WorkItem wiFeatureGroup = WIStore.GetWorkItem(9999); WorkItemLink wiLink = new WorkItemLink(WIStore.WorkItemLinkTypes["Is Produced By"], 9999, 8888); wiFeatureGroup.WorkItemLinks.Add(wiLink); wiFeatureGroup.Save();
|
Deleting a link
To delete a link, you would need to identity the link you want to delete and call the Remove() method on that. Note that you need to save the WorkItem to persist the changes.
WorkItem wiFeatureGroup = WIStore.GetWorkItem(642); foreach (WorkItemLink wiLink in wiFeatureGroup.WorkItemLinks) { if (wiLink.BaseType == BaseLinkType.WorkItemLink) { if(wiLink.LinkType.BaseReferenceName == "Microsoft.VSTS.Common.Produces" && wiLink.LinkType.Name == "Is Produced By") { WorkItem wiDeliverable = WIStore.GetWorkItem(wiLink.TargetId); if (wiDeliverable.Id == 887) { wiFeatureGroup.WorkItemLinks.Remove(wiLink); wiFeatureGroup.Save(); break; } } } } |
All in all, you will generally find that querying, adding and deleting work item links are easy and intuitive.
The ability to add “relations” to work items opens tremendous flexibility and gives you the ability to write cool new applications that use the power of TFS work item store.
Comments
Anonymous
September 26, 2007
PingBack from http://msdnrss.thecoderblogs.com/2007/09/26/querying-on-workitem-links-through-the-api/Anonymous
September 27, 2007
As you know, Rosario comes up with rich linking abilities for workitems and object model to support it.Anonymous
October 01, 2007
Chris Rathjen on TFS Orcas Setup. Trent Nix on Work Item Customization: Set a Field Value That Cannot...Anonymous
October 15, 2008
Team Foundation Server не был бы столь мощным инструментом, объединяющим все роли в проектной группе,