/// <summary> /// Add Query Definition under a specific Query Folder. /// </summary> /// <param name="targetHierarchy">The object that represents the whole of the target query tree</param> /// <param name="query">Query Definition - Contains the Query Details</param> /// <param name="QueryFolder">Parent Folder</param> void MigrateQuery(QueryHierarchy targetHierarchy, QueryDefinition query, QueryFolder parentFolder) { if (parentFolder.FirstOrDefault(q => q.Name == query.Name) != null) { this.totalQueriesSkipped++; Trace.WriteLine($"Skipping query '{query.Name}' as already exists"); } else { // Sort out any path issues in the quertText var fixedQueryText = query.QueryText.Replace($"'{Engine.Source.Config.Project}", $"'{Engine.Target.Config.Project}"); // the ' should only items at the start of areapath etc. if (config.PrefixProjectToNodes) { // we need to inject the team name as a folder in the structure too fixedQueryText = fixedQueryText.Replace($"{Engine.Target.Config.Project}\\", $"{Engine.Target.Config.Project}\\{Engine.Source.Config.Project}\\"); } if (config.SourceToTargetFieldMappings != null) { foreach (var sourceField in config.SourceToTargetFieldMappings.Keys) { fixedQueryText = query.QueryText.Replace($"{sourceField}", $"'{config.SourceToTargetFieldMappings[sourceField]}"); } } // you cannot just add an item from one store to another, we need to create a new object var queryCopy = new QueryDefinition(query.Name, fixedQueryText); this.totalQueriesAttempted++; Trace.WriteLine($"Migrating query '{query.Name}'"); parentFolder.Add(queryCopy); try { targetHierarchy.Save(); // moved the save here for better error message this.totalQueriesMigrated++; } catch (Exception ex) { this.totalQueryFailed++; Trace.WriteLine($"Error saving query '{query.Name}', probably due to invalid area or iteration paths"); Trace.WriteLine($"Source Query: '{query}'"); Trace.WriteLine($"Target Query: '{fixedQueryText}'"); Trace.WriteLine(ex.Message); targetHierarchy.Refresh(); // get the tree without the last edit } } }
/// <summary> /// Execute a WIQL query to return a list of bugs using the .NET client library /// </summary> /// <returns>List of Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.WorkItem</returns> public List <IDefect> GetMyTasks() { List <IDefect> result = new List <IDefect>(); using (TfsTeamProjectCollection service = Service) { WorkItemStore workItemStore = service.GetService <WorkItemStore>(); // get the WorkItemStore service // get the project context for the work item store Project workItemProject = workItemStore.Projects[TeamProjectName]; // search for the 'My Queries' folder QueryFolder myQueriesFolder = workItemProject .QueryHierarchy .FirstOrDefault(qh => qh is QueryFolder && qh.IsPersonal) as QueryFolder; if (myQueriesFolder != null) { // search for the 'SOAP Sample' query QueryDefinition newBugsQuery = myQueriesFolder .FirstOrDefault(qi => qi is QueryDefinition && qi.Name.Equals(myTaskQueryName)) as QueryDefinition; if (newBugsQuery == null) { return(result); } // run the 'SOAP Sample' query WorkItemCollection workItems = workItemStore.Query(newBugsQuery.GetQuery(project: TeamProjectName, user: workItemStore.UserIdentityName)); foreach (WorkItem workItem in workItems) { result.Add(ToDefectItem(workItem)); } } return(result); } }
private static QueryDefinition FindQuery(QueryFolder folders, string queryName) { var result = (QueryDefinition)folders.FirstOrDefault(o => o.Name.Equals(queryName)); if (null != result) { return(result); } foreach (var subFolder in folders) { if (subFolder is QueryFolder) { result = FindQuery((QueryFolder)subFolder, queryName); if (null != result) { return(result); } } } return(null); }
private void lbxQueries_DoubleClick(object sender, EventArgs e) { cbo.Checked = false; rtxtLog.AppendTextWithNewLine("Trying to retrieve Work-items ......................", Color.Green); try { // Get the query var selectedQuery = _myQueryFolder.FirstOrDefault(q => q.Name == lbxQueries.SelectedItem.ToString()) as QueryDefinition; // Run the query if (selectedQuery != null && selectedQuery.QueryType == QueryType.List) { var query = new Query(_workItemStore, selectedQuery.QueryText, GetParamsDictionary()); // Bind flat query reuslt only var workItemCollection = query.RunQuery(); var workItemsDataSource = new List <object>(); foreach (WorkItem workItem in workItemCollection) { workItemsDataSource.Add(new { ID = workItem.Id, Type = workItem.Type.Name, workItem.Title, workItem.State, IterationPath = workItem.Fields["Iteration Path"].Value, workItem.History }); } dgvWorkItemsQueryResult.DataSource = workItemsDataSource; rtxtLog.AppendTextWithNewLine("Retrieved " + workItemCollection.Count + " Work-Items From Query: " + selectedQuery.Name, Color.Green); } else { MessageBox.Show("Please Select a Flat Query", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); rtxtLog.AppendTextWithNewLine("This is not a Flat Query", Color.Red); } } catch (Exception exception) { MessageBox.Show(Utilities.ReadException(exception), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); rtxtLog.AppendTextWithNewLine(Utilities.ReadException(exception), Color.Red); } }
/// <summary> /// Define Query Folders under the current parent /// </summary> /// <param name="targetHierarchy">The object that represents the whole of the target query tree</param> /// <param name="sourceFolder">The source folder in tree on source instance</param> /// <param name="parentFolder">The target folder in tree on target instance</param> private void MigrateFolder(QueryHierarchy targetHierarchy, QueryFolder sourceFolder, QueryFolder parentFolder) { // We only migrate non-private folders and their contents if (sourceFolder.IsPersonal) { Log.LogInformation("Found a personal folder {sourceFolderName}. Migration only available for shared Team Query folders", sourceFolder.Name); } else { this.totalFoldersAttempted++; // we need to replace the team project name in folder names as it included in query paths var requiredPath = sourceFolder.Path.Replace($"{Source.Project}/", $"{Target.Project}/"); // Is the project name to be used in the migration as an extra folder level? if (_Options.PrefixProjectToNodes == true) { // we need to inject the team name as a folder in the structure requiredPath = requiredPath.Replace(_Options.SharedFolderName, $"{_Options.SharedFolderName}/{Source.Project}"); // If on the root level we need to check that the extra folder has already been added if (sourceFolder.Path.Count(f => f == '/') == 1) { var targetSharedFolderRoot = (QueryFolder)parentFolder[_Options.SharedFolderName]; QueryFolder extraFolder = (QueryFolder)targetSharedFolderRoot.FirstOrDefault(q => q.Path == requiredPath); if (extraFolder == null) { // we are at the root level on the first pass and need to create the extra folder for the team name Log.LogInformation("Adding a folder '{Project}'", Source.Project); extraFolder = new QueryFolder(Source.Project); targetSharedFolderRoot.Add(extraFolder); targetHierarchy.Save(); // moved the save here a more immediate and relavent error message } // adjust the working folder to the newly added one parentFolder = targetSharedFolderRoot; } } // check if there is a folder of the required name, using the path to make sure it is unique QueryFolder targetFolder = (QueryFolder)parentFolder.FirstOrDefault(q => q.Path == requiredPath); if (targetFolder != null) { Log.LogInformation("Skipping folder '{sourceFolderName}' as already exists", sourceFolder.Name); } else { Log.LogInformation("Migrating a folder '{sourceFolderName}'", sourceFolder.Name); targetFolder = new QueryFolder(sourceFolder.Name); parentFolder.Add(targetFolder); targetHierarchy.Save(); // moved the save here a more immediate and relavent error message } // Process child items foreach (QueryItem sub_query in sourceFolder) { if (sub_query.GetType() == typeof(QueryFolder)) { MigrateFolder(targetHierarchy, (QueryFolder)sub_query, (QueryFolder)targetFolder); } else { MigrateQuery(targetHierarchy, (QueryDefinition)sub_query, (QueryFolder)targetFolder); } } } }