0

我正在尝试使用托管 TFS API 更新工作项的字段。

但是,某些状态将该字段标记为只读(例如,完成状态),此时我无法修改该字段,即使使用 TFS API 也是如此。我注意到该IsEditable字段返回False,但我无法设置它。

var effort = Convert.ToSingle(workItem.Fields["Effort"].Value);
workItem.Fields["Effort"].Value = effort / 2.0f;

由于我的代码适用于该字段可编辑的每个状态,因此我相当有信心它可以工作。使用 Team Explorer UI 检查工作项时,我可以看到我的更改已在工作项的历史记录中应用和跟踪。这也反映在生成的所有报告中。

字段标记为只读后如何修改?甚至可能吗?(我可以将状态切换回来,以便该字段可编辑,但这是我想避免的事情,因为我不知道这会对我的速度和燃尽图产生什么样的影响。)

4

2 回答 2

2

事实证明,这在使用托管 API 时无法直接完成。使用 Web 服务 API 时,有一个BypassRules可以设置的属性。

Web 服务 API 需要一个 XML 包,因此难点在于创建它。

首先,像往常一样连接到服务器和集合。

var tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
   new Uri(SERVER_URI), new UICredentialsProvider());
tpc.EnsureAuthenticated();

var store = tpc.GetService<WorkItemStore>();
var server = tpc.GetService<WorkItemServer>();

建立连接后,我组装了一个我想要修改的工作项 ID 的列表。就我而言,我需要将所有工作项Efforts除以 2。

XML 包语法相当简单。需要注意的一点是,我明确需要将我的努力值(浮点数)转换为字符串,即使内部类型是双精度。(我可能在这里做错了什么,但最终结果是我想要的。)

private static StringBuilder GetXmlPackage(WorkItemStore store, IEnumerable<int> workItemIds)
{
    var sb = new StringBuilder();
    sb.Append("<Package>");

    foreach (var id in workItemIds)
    {
        var item = store.GetWorkItem(id);
        var effort = Convert.ToSingle(item.Fields["Effort"].Value) / 2.0f;

        sb.AppendFormat("<UpdateWorkItem ObjectType='WorkItem' BypassRules='1' WorkItemID='{0}' Revision='{1}'>", item.Id, item.Rev.ToString());
        sb.Append("<Columns>");
        sb.AppendFormat("<Column Column='Microsoft.VSTS.Scheduling.Effort' Type='Double'><Value>{0}</Value></Column>", XmlConvert.ToString(effort));
        sb.Append("</Columns>");
        sb.Append("<InsertText FieldName='System.History' FieldDisplayName='History'>Updated effort.</InsertText>");
        sb.Append("</UpdateWorkItem>");
    }

    sb.Append("</Package>");
    return sb;
}

最后要做的是调用网络服务器并进行批量更新以修改所有工作项。

private static void UpdateWorkItems(WorkItemStore store, WorkItemServer server, IEnumerable<int> workItemIds)
{
    var sb = GetXmlPackage(store, workItemIds);

    var mthe = new MetadataTableHaveEntry[0];
    string dbStamp;
    IMetadataRowSets rowSets;
    XmlElement outElement;

    var doc = new XmlDocument();
    doc.LoadXml(sb.ToString());

    server.BulkUpdate(
        WorkItemServer.NewRequestId(),
        doc.DocumentElement,
        out outElement,
        mthe,
        out dbStamp,
        out rowSets);
}
于 2012-08-02T13:42:05.613 回答
0

AFAIK 您可以在一定条件下使用 API 执行此操作。运行进程的帐户必须属于Project Collection Service Accounts组。然后,当您创建设置了 BypassRules 标志的 WorkIteMStore 时,类似于下面的代码,您将能够更新字段:

WorkItemStore wis = new WorkItemStore(tpc, WorkItemStoreFlags.BypassRules);

于 2012-10-01T20:02:43.967 回答