C# TFS获取具有关系和子项的项

C# TFS获取具有关系和子项的项,c#,tfs,visual-studio-2017,C#,Tfs,Visual Studio 2017,我需要一些有关Microsoft TFS的帮助。(或VSTS,如果我错了,请纠正我) 我想得到,对于一个给定的项目,所有的关系和孩子。 我能够得到关系,但我不了解子项(例如,给定待办事项下的所有任务,以及所有相关任务/bug等)。最后,我想展示一个树(或者一个包含所有关系的graphQL样式的显示) 这是我课堂的一部分: using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models; using Microsoft.TeamFound

我需要一些有关Microsoft TFS的帮助。(或VSTS,如果我错了,请纠正我)

我想得到,对于一个给定的项目,所有的关系和孩子。 我能够得到关系,但我不了解子项(例如,给定待办事项下的所有任务,以及所有相关任务/bug等)。最后,我想展示一个树(或者一个包含所有关系的graphQL样式的显示)

这是我课堂的一部分:

using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.TeamFoundation.Client;

using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;

public TfsDataProvider(string tfsInstanceUrl, string tfsCollection)
    {
        TfsInstanceUrl = tfsInstanceUrl.TrimEnd('/');
        TfsCollection = tfsCollection;

        TfsUrlPlusCollection = string.Format("{0}/{1}", tfsInstanceUrl, tfsCollection);

        //tfs nuget packages for API version 3.2:
        creds = new VssCredentials();
        creds.Storage = new VssClientCredentialStorage();

        Uri url = new Uri(TfsUrlPlusCollection); //"http://tfs:8080/tfs/aeronautics-100"

        connection = new VssConnection(url, creds);
        wiClient = connection.GetClient<WorkItemTrackingHttpClient>();

        //tracker = new HashSet<int>();
    }



public List<WorkItem> GetWorkItemsByIds(IEnumerable<int> ids)
{
  var wis = wiClient.GetWorkItemsAsync(ids, null, null, WorkItemExpand.Relations).Result;
  return wis;
}
使用Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
使用Microsoft.TeamFoundation.Client;
使用Microsoft.VisualStudio.Services.Client;
使用Microsoft.VisualStudio.Services.Common;
使用Microsoft.VisualStudio.Services.WebApi;
公共TfsDataProvider(字符串tfsInstanceUrl、字符串tfsCollection)
{
TfsInstanceUrl=TfsInstanceUrl.TrimEnd('/');
TfsCollection=TfsCollection;
tfsurlpluscolection=string.Format(“{0}/{1}”,tfsInstanceUrl,tfscolection);
//API 3.2版的tfs nuget软件包:
creds=新的VssCredentials();
creds.Storage=新的VssClientCredentialStorage();
Uri url=新Uri(TfsUrlPlusCollection);/“http://tfs:8080/tfs/aeronautics-100"
连接=新的VssConnection(url、creds);
wiClient=connection.GetClient();
//tracker=newhashset();
}
公共列表GetWorkItemsById(IEnumerable ID)
{
var wis=wiClient.GetWorkItemsAsync(id,null,null,WorkItemExpand.Relations);
返回wis;
}
上面的代码起作用了,我收到了所有的项目和它们的关系,然后我可以通过id获得这些关系,并构建一个树来显示。 我的问题是,我不明白我怎样才能把所有的孩子都带回来

目前,我想向这个函数发送一个id数组(此时为1个id),并递归地获取它的所有子项和关系。看来我只得到了关系


我使用的是2017版TFS,API版本是3.2

所有链接的工作项都包含在关系中,因此您的代码已经获得了子工作项。下一步是检查关系类型,以确定哪个是相关工作项,哪个是子工作项

    foreach (WorkItem wi in wis)
    {
        if (wi.Relations != null)
        {
            foreach (WorkItemRelation wir in wi.Relations)
            {
                Console.WriteLine(wir.Rel);
                Console.WriteLine(wir.Url);
            }
        }
    }
链接类型:

Child:   System.LinkTypes.Hierarchy-Forward
Parent:  System.LinkTypes.Hierarchy-Reverse
Related: System.LinkTypes.Related

只需递归地获取所有子工作项

例如:

 private static void GetWorkItemsTest()
        {
           //var creds = new VssCredentials();
           // creds.Storage = new VssClientCredentialStorage();
            VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.VssBasicCredential(string.Empty, "{PAT}"));
            Uri url = new Uri("https://starain.visualstudio.com"); 

           var connection = new VssConnection(url, c);
           var wiClient = connection.GetClient<WorkItemTrackingHttpClient>();
            IEnumerable<int> ids = new List<int> { 851, 180 };
            var wis = wiClient.GetWorkItemsAsync(ids, null, null, WorkItemExpand.Relations).Result;
            foreach (WorkItem wi in wis)
            {
                Console.WriteLine(wi.Id);
                GetChildrenWIT(wiClient, wi, 1,new List<int> { wi.Id.Value});
            }
        }
        private static void GetChildrenWIT(WorkItemTrackingHttpClient witClient, WorkItem child, int width,List<int> existingWit)
        { 
            if (child.Relations != null)
            {
                foreach (WorkItemRelation wir in child.Relations)
                {
                    var indent = new string('-', width);
                    int id = int.Parse(wir.Url.Split('/').Last());
                    if(!existingWit.Contains(id))
                    {
                        Console.WriteLine(string.Format("{0}{1}", indent, wir.Rel));
                        var childwit = witClient.GetWorkItemAsync(id, null, null, WorkItemExpand.Relations).Result;
                        existingWit.Add(childwit.Id.Value);
                        Console.WriteLine(string.Format("{0}-{1}", indent, childwit.Id));
                        GetChildrenWIT(witClient, childwit, width+1, existingWit);
                    }         
                }
            }
        }
private static void GetWorkItemsTest()
{
//var creds=新的VssCredentials();
//creds.Storage=新的VssClientCredentialStorage();
VssCredentials c=新的VssCredentials(新的Microsoft.VisualStudio.Services.Common.vssbasiccredentials(string.Empty,“{PAT}”);
Uri url=新的Uri(“https://starain.visualstudio.com"); 
var连接=新的VssConnection(url,c);
var wiClient=connection.GetClient();
IEnumerable id=新列表{851180};
var wis=wiClient.GetWorkItemsAsync(id,null,null,WorkItemExpand.Relations);
foreach(wis中的工作项目wi)
{
控制台写入线(wi.Id);
GetChildrenWIT(wiClient,wi,1,新列表{wi.Id.Value});
}
}
私有静态void GetChildrenWIT(WorkItemTrackingHttpClient witClient、WorkItem child、整型宽度、列表现有Wit)
{ 
if(child.Relations!=null)
{
foreach(子关系中的工作项关系)
{
var indent=新字符串('-',宽度);
int id=int.Parse(wir.Url.Split('/').Last());
如果(!existingWit.Contains(id))
{
WriteLine(string.Format(“{0}{1}”,indent,wir.Rel));
var childwit=witClient.GetWorkItemAsync(id,null,null,WorkItemExpand.Relations);
existingWit.Add(childwit.Id.Value);
WriteLine(string.Format(“{0}-{1}”,缩进,childwit.Id));
GetChildrenWIT(witClient,childwit,宽度+1,现有Wit);
}         
}
}
}
结果如下:


我刚刚遇到了一个类似的问题,要获得有关关系的信息,您必须使用GetWorkItemAsync方法的WorkItemExpand参数:

var item = client.GetWorkItemAsync(c_projectName, id, null, null, WorkItemExpand.Relations).Result;

如果不使用此参数,关系属性将为空。

谢谢Eddie Chen!这是我遗漏的部分,链接类型。谢谢你的回答!我已经开始使用类似于您的示例的方法,但我得到了堆栈溢出异常,可能是因为循环依赖,每个子级都有一个到父级的链接,我尝试递归地获取它。不管怎样,Eddie Chen关于链接类型的提示帮助我找到了答案。再次感谢你。