Work Item Tracking Queries Object Model in 2010
The following post was written by Smitha Saligrama, a software development engineer in test on the work item tracking team for Team Foundation Server.
To allow better organization and permissions on queries in Team Foundation Server 2010 we added query folders. Query folders allow you to organize both your personal queries and project queries into nested folders:
Because of this change, there are some changes to the work item tracking queries object model.
Object Model
StoredQuery and StoredQueryCollection are now obsolete and are replaced by new types, QueryDefinition and QueryFolder, both deriving from the same base class (QueryItem). A QueryFolder contains a collection of QueryItem objects, each of which may be a QueryFolder or a QueryDefinition.
Samples
Adding a new query folder
QueryFolder folder = new QueryFolder("My New Folder");
QueryFolder parentFolder = GetMyQueriesFolder();
parentFolder.Add(folder);
myproject.QueryHierarchy.Save();
//OR
QueryFolder folder = new QueryFolder("My New Folder", GetMyQueriesFolder());
myproject.QueryHierarchy.Save();
Adding a new query
QueryDefinition query = new QueryDefinition("My Query", "Select * from WorkItems Where [System.AssignedTo] = @me", parentFolder);
myproject.QueryHierarchy.Save();
//OR
QueryDefinition query = new QueryDefinition("My Query", "Select * from WorkItems Where [System.AssignedTo] = @me");
parentFolder.Add(query);
myproject.QueryHierarchy.Save();
Renaming a query or folder
//QueryItem folderOrQuery
folderOrQuery.Name = "My Renamed folder";
myproject.QueryHierarchy.Save();
Moving a query or folder
//QueryItem queryItem
//QueryFolder targetFolder
targetFolder.Add(queryItem);
targetFolder.Project.QueryHierarchy.Save();
Deleting a query or folder
QueryItem query = … // find the query or folder you want to delete
query.Delete();
Project.QueryHierarchy.Save();
Complete Sample
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System.Text;
namespace WorkItemTrackingSamples
{
class QueryFolderSample
{
private static Project myproject = null;
static void Main(string[] args)
{
TfsTeamProjectCollection coll = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("TfsCollectionUrl"));
WorkItemStore store = new WorkItemStore(coll);
myproject = store.Projects["projectName"];
//Add Folder
QueryFolder myNewfolder = AddNewFolder("My New Folder 1");
//Add Query
QueryDefinition myQuery = AddNewQuery(myNewfolder);
//Rename the folder
RenameQueryItem(myNewfolder);
//Add a new folder and move
QueryFolder myMovefolder = AddNewFolder("My New Folder 2");
MoveQueryItem(myNewfolder, myMovefolder);
//Delete the sample
DeleteQueryItem(myMovefolder);
}
/// <summary>
/// Create a new "My New Folder" folder under My Queries
/// </summary>
/// <returns>Newly created folder</returns>
public static QueryFolder AddNewFolder(string folderName)
{
QueryFolder folder = new QueryFolder(folderName, GetMyQueriesFolder());
myproject.QueryHierarchy.Save();
return folder;
}
/// <summary>
/// Adds a query
/// </summary>
/// <param name="parentFolder">Parent Folder where the query will be added</param>
/// <returns></returns>
public static QueryDefinition AddNewQuery(QueryFolder parentFolder)
{
QueryDefinition query = new QueryDefinition("My Query", "SELECT [System.Title] FROM WorkItems WHERE [System.AssignedTo] = @me", parentFolder);
myproject.QueryHierarchy.Save();
return query;
}
/// <summary>
/// Will rename a QueryFolder or a QueryDefinition
/// </summary>
/// <param name="folderOrQuery">Folder or QUery</param>
public static void RenameQueryItem(QueryItem folderOrQuery)
{
folderOrQuery.Name = "My Renamed folder";
myproject.QueryHierarchy.Save();
}
/// <summary>
/// Moves a query folder or query
/// </summary>
/// <param name="query">QueryFolder or Query to move</param>
/// <param name="targetFolder">Target Folder</param>
public static void MoveQueryItem(QueryItem queryItem, QueryFolder targetFolder)
{
targetFolder.Add(queryItem);
targetFolder.Project.QueryHierarchy.Save();
}
/// <summary>
/// Delete Query folder or Query
/// </summary>
/// <param name="queryItem">Folder or QUery to delete</param>
public static void DeleteQueryItem(QueryItem queryItem)
{
queryItem.Delete();
myproject.QueryHierarchy.Save();
}
/// <summary>
/// Returns the My Queries folder
/// </summary>
/// <returns>My Queries folder</returns>
public static QueryFolder GetMyQueriesFolder()
{
foreach (QueryFolder folder in myproject.QueryHierarchy)
{
if (folder.IsPersonal == true)
return folder;
}
throw new Exception("Cannot find the My Queries folder");
}
}
}
Comments
Anonymous
June 18, 2010
Great example. Can you show us something about creating new TFS projects please?Anonymous
June 24, 2010
Any chance we could get a sample solution file and project files with all of this wired up? I'd love to see a sample that actually does something as well.Anonymous
July 02, 2010
Hi Allen, I have attached a sample application. Hope it helps, SmithaAnonymous
July 12, 2010
If you want to use OM to run Linked queries, below is a sample public WorkItemLinkInfo[] RunLinkQuery(string wiql) { Query query = new Query(m_workItemStore, wiql) WorkItemLinkInfo[] workItemLinkInfoArray = null; if (query.IsLinkQuery) { workItemLinkInfoArray = query.RunLinkQuery(); } else { throw new Exception("Run link query fail. Query passed is not a link query"); } return workItemLinkInfoArray; }