I'm trying to access saved TFS queries by their full path (deeper than 'My Queries'/'Shared Queries') , and the query name.
The scenario is that users can add the path to their team directory, and the names of the their work item queries into a config xml file. I read the xml and get the data.
example XML
<Teams>
<Team name ="MyTeam">
<Query project="MyProj" queryfolder="Shared Queries/blah/blah2/MyTeamFolder" queryName="MyTeams WorkItems - All Workitems"/>
</Team>
</Teams>
I'm looking to use the 'queryfolder' and the 'queryName' to find the query in TFS What I have so far, that works for the Root directories ('My Queries'/'Shared Queries'), but I can't figure out how to get something working for deeper paths.
This does not work:
QueryHierarchy queryRoot = workItemStore.Projects["MyProj"].QueryHierarchy;
QueryFolder folder = (QueryFolder)queryRoot["Shared Queries/blah/blah2/MyTeamFolder"];
QueryDefinition query = (QueryDefinition)folder["MyTeams WorkItems - All Workitems"];
string queryResults = query.QueryText;
This will error out on finding the folder QueryFolder folder = (QueryFolder)queryRoot[".."]
with KeyNotFoundException
changing the folder with 'Shared Queries' or 'My Queries', its able to find the folder, but then would get the same exception when trying to find the Query by its' name. And as expected, if the query is located in the root folder (shared/my queries), it works fine.
So how do I search deeper than just the root folder?
(all internet searches so far have yielded only examples where the root folder is being used)
This self-recursive method will find your query from the query tree if it exists:
static QueryDefinition GetQueryDefinitionFromPath(QueryFolder folder, string path)
{
return folder.Select<QueryItem, QueryDefinition>(item =>
{
return item.Path == path ?
item as QueryDefinition : item is QueryFolder ?
GetQueryDefinitionFromPath(item as QueryFolder, path) : null;
})
.FirstOrDefault(item => item != null);
}
Your example is given, call
var myquery = GetQueryDefinitionFromPath( (QueryFolder)workItemStore.Projects["MyProj"].QueryHierarchy, "Shared Queries/blah/blah2/MyTeamFolder/MyTeams WorkItems - All Workitems" );
The recursive answer above can work but I had issues with it due to the fact that the item.Path includes the entire path from the root and the path I was passing in did not; resulting in a null value as the final result. I also found that it does a lot of extra work as it touches every folder in the entire tree on its way to your desired folder.
I opted for a simple drill down looking specifically for the nodes I knew would/should be there making the method much more efficient by ignoring all the chaff. I pass in the full path from the root and use the string.Split('/').Skip(1).ToArray() to move past the root node avoiding the KeyNotFoundException since the root does not include itself. I intentionally did not handle the case where the folder was not found since we are in complete control of what we pass in and should only be providing a valid path.
Code is:
private static QueryFolder GetQueryFolderFromPath(QueryFolder folder, string path)
{
var pathNodes = path.Split('/').Skip(1).ToArray();
foreach(var node in pathNodes)
{
folder = (QueryFolder)folder[node];
if (folder != null && folder.Path.Equals(path))
break;
}
return folder;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With