Reputation: 117
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)
Upvotes: 5
Views: 2723
Reputation: 11
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;
}
Upvotes: 1
Reputation: 46
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" );
Upvotes: 3
Reputation: 11
You can parse the folder full path to the set of subfolders and then create a loop to "move down" the folder tree. You get the QueryFolder
instance for the next subfolder and assign it to the same variable until you reach the last one.
Here is the implementation of this idea I used in my project:
string folderPath = "Shared Queries/blah/blah2/MyTeamFolder";
string currentSubfolder = folderPath.IndexOf("/") > 0 ?
folderPath.Substring(0, folderPath.IndexOf("/")) :
folderPath;
QueryFolder queryFolder = (QueryFolder)workItemStore.Projects["MyProj"].QueryHierarchy[currentSubfolder];
while (folderPath.IndexOf("/") > 0)
{
folderPath = folderPath.Substring(folderPath.IndexOf("/") + 1);
currentSubfolder = folderPath.IndexOf("/") > 0 ?
folderPath.Substring(0, folderPath.IndexOf("/")) :
folderPath;
queryFolder = (QueryFolder)queryFolder[currentSubfolder];
}
After that, you will be able to use the query folder variable to work with queries inside it.
Upvotes: 0