/// <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);
            }
        }
Example #3
0
        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);
                    }
                }
            }
        }