Когда вы выполните RunQuery () для запроса flat , вы получите успешный ответ. Но если вы выполните RunQuery () для связанного запроса ( tree или one-hop WIQL), вы увидите это сообщение об ошибке.
Для выполнения связанного запроса необходимо использовать метод RunLinkQuery () вместо RunQuery () в классе Query. Это возвращает массив объектов WorkItemLinkInfo, который содержит следующие поля: SourceId, TargetId, LinkTypeId и IsLocked.
Ниже приведен пример запроса дерева:
SELECT [System.Id], [System.State], [System.WorkItemType]
FROM WorkItemLinks
WHERE
(
Source.[System.TeamProject] = 'TFSTestProject'
AND Source.[System.WorkItemType] = 'Requirement'
AND Source.[System.State] NOT IN ('Proposed', 'Completed')
)
AND [System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward'
AND Target.[System.WorkItemType] <> ''
ORDER BY [System.Id] mode(Recursive)
А ниже приведен пример выполнения запроса дерева в c #:
private List<WorkItemViewModel> GetWorkItemTree(string query)
{
var treeQuery = new Query(_workItemStore, query);
var links = treeQuery.RunLinkQuery();
var workItemIds = links.Select(l => l.TargetId).ToArray();
query = "SELECT * FROM WorkItems";
var flatQuery = new Query(_workItemStore, query, workItemIds);
var workItemCollection = flatQuery.RunQuery();
var workItemList = new List<WorkItemViewModel>();
for (int i = 0; i < workItemCollection.Count; i++)
{
var workItem = workItemCollection[i];
if (workItem.Type.Name == "Requirement")
{
var model = new WorkItemViewModel()
{
Id = workItem.Id,
RequestNo = workItem.Fields["MyCompany.RequestNumber"].Value.ToString(),
Title = workItem.Title,
WorkItemType = workItem.Fields["MyCompany.WorkItemType"].Value.ToString(),
Priority = workItem.Fields["MyCompany.Priority"].Value.ToString()
};
workItemList.Add(model);
}
else
{
switch (workItem.Type.Name)
{
case "Task":
var task = new TFSTask()
{
Name = workItem.Title,
Activity = workItem.Fields["MyCompany.Activity"].Value.ToString(),
Start = (DateTime?)workItem.Fields["MyCompany.ActivityStart"].Value,
Due = (DateTime?)workItem.Fields["MyCompany.ActivityFinish"].Value,
Status = workItem.State
};
workItemList.Last().Tasks.Add(task);
break;
case "Issue":
var issue = new TFSIssue()
{
Name = workItem.Title,
Created = workItem.CreatedDate,
Due = (DateTime?)workItem.Fields["MyCompany.ActivityDue"].Value,
Status = workItem.State
};
workItemList.Last().Issues.Add(issue);
break;
default:
break;
}
}
}
return workItemList;
}
Полезные ссылки:
Кстати, вы также можете использовать API TFS Rest для запуска связанного запроса:
https://docs.microsoft.com/en-us/rest/api/vsts/wit/wiql/query%20by%20wiql