When using TFS it is good practice when checking in to associate with a work item to describe the cause for change. This creates a relationship between the change set created during the check in and the work item. It’s also exposed through in the TFS API as a property on the change set known as WorkItems. The great thing about this is that it lets you traverse the link in a natural manner, without having to set up the link queries yourself. This is not without its gotcha’s however, as I discovered…
To get your hands on the change set, you’ll initially need to set up a version control server object. Something to watch out for here is when scoping the lifetime of your server object that you’re going to use to get the change set you’ll need to take into account when the work item query is going to happen. You see the property is actually a bit clever about how and when it loads the work items that populate the list. When you obtain your change set, the version control service that you’re using is stored in a property of the change set.
Enter the dangers of not being scope aware!
The issue I am alluding to not so subtly to is one where you de-scope the original team foundation server instance, leaving the change set without an internal (open) server reference. This normally wouldn’t be an issue, as we’ve already got the change set – right? Some digging in reflector shows that our WorkItems collection is actually a lazy load collection, populated on first call and cached thereafter. The process is roughly as follows:
When you run your first get on the list, an instance of the WorkItemStore service is created and a query executed to get the referencing work items. The list of referencing work item URI’s is then used to fetch the work items, and populate an internal list (effectively caching the list for future reference). A clone of the internal list is then returned as the result.
What does this mean to you?
Well, if you scope your server instance with a using statement that is closed before you make use of the WorkItems property your server object (and the internal one used by the WorkItem property) will have already been closed and you’ll recieve a null reference exception. There are 2 ways around this, which you chose is dependent on your scenario. First, include your code that will query the work item list in the appropriate scope. This will extend the lifetime of your server object by the execution time of the extra code at least. The second option is to make an immediate call to the WorkItems property to populate and return you the list, and then allow the server object to be disposed as normal. This means the server object will be closed earlier, but you’ll be carrying around the work item list in memory for longer.