Today I’m building a small utility and have a requirement to execute a stored work item query from within Team Foundation Server 2010. Previously I’d used the StoredQueries collection on the Project instance to find a query by name … however it would appear that this was depreciated as part of the TFS2010 release.
I was surprised to find that there doesn’t seem to be a simple replacement for finding a specified stored query by name – part of me thinks I must be missing a simpler solution, however if anyone else is encountering the same issue I hope that the following code snippet will be of use.
Required namespaces:
- Microsoft.TeamFoundation.Client
- Microsoft.TeamFoundation.WorkItemTracking.Client
/// <summary>
/// <para>Find the TFS QueryDefinition for a specified Team Project</para>
/// <para>Note that if multiple queries match the requested queryName
/// only the first will be used</para>
/// </summary>
/// <param name=”tfsUrl”>URL to the TFS project, including the
/// collection name (Eg, http://tfsserver:8080/tfs/DefaultCollection)</param>
/// <param name=”projectName”>Name of TFS Team Project</param>
/// <param name=”queryName”>Name of Stored Query. Note if multiple
/// exist the first found will be used</param>
/// <returns></returns>
public static QueryDefinition FindQueryItem(string tfsUrl, string projectName, string queryName)
{
// Setup the connection to TFS
TfsTeamProjectCollectionprojectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(tfsUrl));
WorkItemStore workItemStore = projectCollection.GetService<WorkItemStore>();
Project project = workItemStore.Projects[projectName];
return FindQueryItem(queryName, project.QueryHierarchy);
}
///<summary>
/// Recursively find the QueryDefinition based on the requested queryName.
///<para>Note that if multiple queries match the requested queryName
/// only the first will be used</para>
///</summary>
///<param name=”queryName”>Name of Stored Query. Note if multiple exist
/// the first found will be used</param>
///<param name=”currentNode”>Pointer to the current node in the recursive search</param>
///<returns>QueryDefinition</returns>
private static QueryDefinition FindQueryItem(string queryName, QueryItem currentNode)
{
// Attempt to cast to a QueryDefinition
QueryDefinitionqueryDefinition = currentNode as QueryDefinition;
// Check if we’ve found a match
if (queryDefinition != null && queryDefinition.Name == queryName)
return queryDefinition;
// Attempt to cast the current node to a QueryFolder
QueryFolder queryFolder = currentNode as QueryFolder;
// All further checks are for child nodes so if this is not an
// instance of QueryFolder then no further processing is required.
if (queryFolder == null)
return null;
// Loop through all the child query item
foreach (QueryItem qi in queryFolder)
{
// Recursively call FindQueryItem
QueryDefinition ret = FindQueryItem(queryName, qi);
// If a match is found no further checks are required
if (ret != null)
return ret;
}
return null;
}
There is a little mistake – it should check like so:
if ((queryDefinition != null) && (queryDefinition.ToString() == queryName))