In TFS, some of work items are assigned. For those tasks test cases work items created and linked to the appropriate tasks.
I want to get the list of test cases linked for a particular task. How to write query to get it?
You have to use link query to get that:
SELECT [System.Id], [System.Title], [System.AssignedTo], [System.State]
FROM WorkItemLinks
WHERE ([Source].[System.TeamProject] = #project AND
[Source].[System.WorkItemType] = 'Test Case') And
([System.Links.LinkType] <> '') And ([Target].[System.Id] = #taskId)
ORDER BY [System.Id] mode(MayContain)
Here's the code to run it:
var tpc = new TfsTeamProjectCollection("http://localhost:8080/tfs/DefaultCollection");
var store = tpc.GetService<WorkItemStore>();
var queryContext = new Dictionary<string, string>();
queryContext.Add("project", "<team project name>");
queryContext.Add("taskId", "<task ID you are interested in>");
var query = new Query(store, "<WIQL query text>", queryContext);
var result = query.RunLinkQuery();
Related
I am using a multi match query like so:
var builder = QueryBuilders.multiMatchQuery(search, "projectName", "jobNumber");
var query = new NativeSearchQueryBuilder()
.withQuery(builder)
.withPageable(pageable)
.build();
var result = searchOperations.search(query, Foo.class);
Now I need to make sure that the _id field also matches the FooId field. How do I create a query to do that and combine it with my multi match query?
If both clauses are mandatory, you can combine them using must method of BoolQueryBuilder:
var builder = new BoolQueryBuilder()
.must(QueryBuilders.multiMatchQuery(search, "projectName", "jobNumber"))
.must(QueryBuilders.termQuery("_id", fooId));
var query = new NativeSearchQueryBuilder()
.withQuery(builder)
.withPageable(pageable)
.build();
var result = searchOperations.search(query, Foo.class);
Or you can define the clause by id as a filter having the same result:
var builder = QueryBuilders.multiMatchQuery(search, "projectName", "jobNumber");
var filter = QueryBuilders.termQuery("_id", fooId)
var query = new NativeSearchQueryBuilder()
.withQuery(builder)
.withFilter(filter)
.withPageable(pageable)
.build();
var result = searchOperations.search(query, Foo.class);
The following function is designed to get my spreadsheet, add a new tab, insert a new tab with a query that runs, and then save the new tab under a new name.
Everything works except the new tab always is inserted as then next unused tab number and not renamed. Tried a number of variations (setName, etc.) and nothing seems to work.
Help!
function costIncome() {
var spreadsheetId =https://docs.google.com/spreadsheets/d/thisIsTheSheetID/edit';
var targetRange = 'PlaySheet!B:F';
var SELECT = 'select B,E,F,sum(C) ';
var WHERE = ' ';
var GROUPBY = ' group by B,F,E order by D,B';
var HAVING = ' ';
var SQL = SELECT + WHERE + GROUPBY + HAVING;
//var SQL = 'select B,E,F,sum(C) group by B,F,E';
var Query = '=QUERY('+targetRange+',\"'+SQL+'\")';
var currentDoc = SpreadsheetApp.openByUrl(spreadsheetId);
currentDoc.insertSheet('costfunds');
var pushQuery = currentDoc.getRange(1, 1).setFormula(Query);
var pullResult = currentDoc.getDataRange().getValues();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); // Get Active spreadsheet object
var sh = spreadsheet.getActiveSheet(); // Get Active sheet's object
sh.setName("Name changed!")
}
I found an answer elsewhere
SpreadsheetApp.flush();
tempSheet.setName("MYCHANGEDSHEET");
I lost the link for the original post, but thanks to him/her/them.
So many things are poorly functioning/documented in G-Sheets. SMH.
I'm using WorkItemTrackingHttpClient.QueryByWiqlAsync to retrieve the results of a query. It returns the top 200 records by default. It has a top param which you can use to specify a value less then 200.
However, the result of my query is greater than 200 records. Does anyone know how to execute a query using the TFS client with proper paging .i.e. page and page size? For example, return page 10 where the page count is say 50.
I've looked around but can't see how to do this using the client which is surprising as the capability seems so fundamental.
I'm using the Nuget Package Microsoft.TeamFoundationServer.Client 16.153.0. I'm also connecting to TFS 2017 onprem.
Yeah, we can only return a list of work items which limits to Maximum 200 by calling the API. It's by design, see Work Items - List for details.
However we can use WIQL Queries to retrieve data from Azure DevOps. It is very flexible and it could be used in any situation. See WIQL queries and Azure DevOps Rest API for WIQL Queries
To get all the work items, we can try following steps:
Execute a stored query using the work item query API to retrieve a
list of work item IDs
Split the list of work item IDs into groups of 200, which is the
maximum batch size that the work items API supports
Call the work items API for each list of 200 work item IDs to get
the work item details.
You can reference this thread for details.
Besides, below code for your reference, it's working for me:
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QueryWorkitems0619
{
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://tfs2017:8080/tfs/DefaultCollection");
//string PAT = "xxxx";
string project = "SCRUM-TFVC";
//VssBasicCredential credentials = new VssBasicCredential(user, PAT);
VssCredentials credentials = new VssClientCredentials();
credentials.Storage = new VssClientCredentialStorage();
//create a wiql object and build our query
Wiql wiql = new Wiql()
{
Query = "Select * " +
"From WorkItems " +
"Where [Work Item Type] = 'Product Backlog Item' " +
"And [System.TeamProject] = '" + project + "' " +
"And [System.State] <> 'Closed' " +
"Order By [State] Asc, [Changed Date] Desc"
};
//create instance of work item tracking http client
using (WorkItemTrackingHttpClient workItemTrackingHttpClient = new WorkItemTrackingHttpClient(uri, credentials))
{
//execute the query to get the list of work items in the results
WorkItemQueryResult workItemQueryResult = workItemTrackingHttpClient.QueryByWiqlAsync(wiql).Result;
//Splict the query result (the list of work item IDs) into groups of 200.
var QueryGroups = from i in Enumerable.Range(0, workItemQueryResult.WorkItems.Count())
group workItemQueryResult.WorkItems.ToList()[i] by i / 200;
foreach (var QueryGroup in QueryGroups)
{
//some error handling
if (QueryGroup.Count() != 0)
{
//need to get the list of our work item ids and put them into an array
List<int> list = new List<int>();
foreach (var item in QueryGroup.ToList())
{
list.Add(item.Id);
}
int[] arr = list.ToArray();
//build a list of the fields we want to see
string[] fields = new string[3];
fields[0] = "System.Id";
fields[1] = "System.Title";
fields[2] = "System.State";
//get work items for the ids found in query
var workItems = workItemTrackingHttpClient.GetWorkItemsAsync(arr, fields, workItemQueryResult.AsOf).Result;
Console.WriteLine("\n\n----------------------------------------------------------------");
Console.WriteLine("\nQuery Results: {0} items found for Group {1}", workItems.Count, QueryGroup.Key);
Console.WriteLine("\n----------------------------------------------------------------");
//loop though work items and write to console
foreach (var workItem in workItems)
{
Console.WriteLine("ID:{0} Title:{1} State:{2}", workItem.Id, workItem.Fields["System.Title"], workItem.Fields["System.State"]);
}
}
}
Console.ReadLine();
}
}
}
}
I'm looking around for a good example to work with TFS 2010 collections,projects, and workitems to start with.
I am able to iterate through collections and Projects using the following code (thanks to original coder)
Dim tfsServer As String = "http://test.domain.com:8080/tfs"
tfsServer = tfsServer.Trim()
Dim tfsUri As Uri
tfsUri = New Uri(tfsServer)
Dim configurationServer As New TfsConfigurationServer(tfsUri)
configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri)
' Get the catalog of team project collections
Dim collectionNodes As ReadOnlyCollection(Of CatalogNode)
Dim gVar As Guid() = New Guid() {CatalogResourceTypes.ProjectCollection}
collectionNodes = configurationServer.CatalogNode.QueryChildren(gVar, False, CatalogQueryOptions.None)
Dim strName As New StringBuilder
Dim strCollection As New StringBuilder
For Each collectionNode In collectionNodes
Dim collectionId As Guid = New Guid(collectionNode.Resource.Properties("InstanceID"))
strName.Length = 0
Dim teamProjectCollection As New TfsTeamProjectCollection(tfsUri)
teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId)
Response.Write("Collection:" & teamProjectCollection.Name & "<br/>")
' Get a catalog of team projects for the collection
Dim hVar As Guid() = New Guid() {CatalogResourceTypes.TeamProject}
Dim projectNodes As ReadOnlyCollection(Of CatalogNode)
projectNodes = collectionNode.QueryChildren(hVar, False, CatalogQueryOptions.None)
' List the team projects in the collection
For Each projectNode In projectNodes
strName.AppendLine(projectNode.Resource.DisplayName & "<br>")
'System.Console.WriteLine(" Team Project: " + projectNode.Resource.DisplayName)
Next
Response.Write(strName.ToString())
Next
I want to read specific project from a collection and iterate through workitems (tasks,bugs,issues,etc). Any help would be highly appreciated.
Thanks.
You can run any query you like in the teamProjectCollection - level with:
WorkItemStore workItemStore = (WorkItemStore)teamProjectCollection.GetService(typeof(WorkItemStore));
WorkItemCollection queryResults = workItemStore.Query(query);
foreach (WorkItem workitem in queryResults)
{
Console.WriteLine(workitem.Title);
}
Now you only have to formulate the query - string in something that provides you with what you need.
Queries are WIQL - like. This very basic can give you all work items within a TeamProject:
SELECT [System.Id], [System.WorkItemType], [System.Title], [System.AssignedTo], [System.State] FROM WorkItems WHERE [System.TeamProject] = #project
#project is in our case here the projectNode.Resource.DisplayName
(You can save any query you 've graphically set in TFS with 'Save as' as a *.wiq file & then use it's content programmatically)
I've got the following WIQL query for a TFS project:
string query = "SELECT * FROM Issue WHERE [System.TeamProject] = #Project "+
"AND [Assigned To] IN (#AssignedTo)";
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("Project","test");
parameters.Add("AssignedTo","'chris','tfsuser'");
WorkItemStore.Query(query, parameters);
This is being run via the .NET TFS API.
My problem is with the AssignedTo parameter. How is this meant to be specified? I've tried it as a string[], List<string> as well as with and without quotes as above. Each one doesn't seem to work.
I understand what you're trying to do, but it doesn't look like it's possible. The query that you want is this:
WHERE [System.AssignedTo] in ('John Smith', 'Jane Citizen')
Which is semantically the same as this:
WHERE [System.AssignedTo] = 'John Smith' OR [System.AssignedTo] = 'Jane Citizen'
The only way I can work out how to achieve it in code is by specifying the identities as separate parameters:
TfsTeamProjectCollection tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://localhost:8080/tfs/"));
WorkItemStore wis = tfs.GetService<WorkItemStore>();
Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("parameter1", "John Smith");
values.Add("parameter2", "Jane Citizen");
Query query = new Query(wis, "SELECT [System.Id] FROM WorkItems WHERE [System.AssignedTo] IN (#parameter1, #parameter2)", values);
WorkItemCollection workItems = wis.Query(query.QueryString);
WorkItem workItem = workItems[0];
Assigned To field is actually [System.AssignedTo]. I don't believe using the display name of the field will work.