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:

image

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.

 image

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");
        }
    }
}

SampleConsoleApplication.zip

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, Smitha

  • Anonymous
    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;       }