使用C#通过WIQL获取AzureDevOps工作项链接时遇空值错误
解决WIQL查询工作项链接时的"Value cannot be null. (Parameter 'source')"错误
错误原因
你用查询普通工作项的QueryWorkItems方法执行WorkItemLinks类型的WIQL查询,两者返回的数据结构完全不匹配:
- 普通工作项查询返回扁平化的WorkItem列表
- WorkItemLinks查询返回包含源工作项、目标工作项、链接类型的层级结构,原方法无法解析这种结构,导致参数
source为空抛出异常。
另外你的WIQL存在潜在语法问题:TEAM_PROJECT作为字符串类型,未加单引号会触发查询语法错误。
修正步骤
1. 修复WIQL语法
给TEAM_PROJECT添加单引号,避免语法错误:
string query = "Select * From WorkItemLinks" + " WHERE Source.[System.TeamProject] = '" + TEAM_PROJECT + "'" + " AND Target.[System.TeamProject] = '" + TEAM_PROJECT + "'" + " AND [System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward' " + " AND Source.[System.Id] = '119943' " + " AND Source.[System.State] = 'Active' ";
2. 使用专门的链接查询方法
替换原有的QueryWorkItems,改用支持WorkItemLinks查询的方法(基于Azure DevOps .NET SDK的QueryByWiqlAsync,处理WorkItemLinkResult结构):
using Microsoft.TeamFoundation.WorkItemTracking.WebApi; using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models; using Microsoft.VisualStudio.Services.Common; // 初始化工作项跟踪客户端 var credentials = new VssBasicCredential(string.Empty, personalAccessToken); var wiqlClient = new WorkItemTrackingHttpClient(new Uri($"https://dev.azure.com/{orgName}/"), credentials); // 构造WIQL查询对象 var wiql = new Wiql { Query = query }; // 执行链接查询 var linkResult = await wiqlClient.QueryByWiqlAsync(wiql); // 遍历提取链接相关的工作项信息 if (linkResult.WorkItemRelations != null) { foreach (var relation in linkResult.WorkItemRelations) { // 源工作项(部分场景下可能为null) var sourceWorkItem = relation.Source != null ? await wiqlClient.GetWorkItemAsync(relation.Source.Id, fields) : null; // 目标工作项 var targetWorkItem = await wiqlClient.GetWorkItemAsync(relation.Target.Id, fields); // 链接类型 var linkType = relation.Rel; // 按需处理获取到的内容 Console.WriteLine($"源ID: {sourceWorkItem?.Id}, 目标ID: {targetWorkItem.Id}, 链接类型: {linkType}"); } }
3. 优化异步调用方式(可选)
避免使用GetAwaiter().GetResult()这种阻塞式调用,直接用await异步执行,降低死锁风险:
// 替换原阻塞代码,直接异步等待结果 var linkResult = await wiqlClient.QueryByWiqlAsync(wiql);
内容的提问来源于stack exchange,提问作者NottmTony
相关产品推荐
相关产品推荐

