查询 Bug、任务和其他工作项
可以为 bug、任务、工作项的其他工作项使用一个 WorkItemStore.Query 方法或 Query 对象之间的类型和链接查询。这些查询使用工作项查询语言 (WIQL),类似于 Transact-SQL。
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(
new Uri("https://server:8080/tfs/DefaultCollection"));
WorkItemStore workItemStore = (WorkItemStore)tpc.GetService(typeof(WorkItemStore));
WorkItemCollection queryResults = workItemStore.Query("
Select [State], [Title]
From WorkItems
Where [Work Item Type] = 'User Story'
Order By [State] Asc, [Changed Date] Desc");
Dim collectionUri As Uri
collectionUri = New Uri("https://Server:8080/tfs/DefaultCollection")
Dim tpc As New TfsTeamProjectCollection(collectionUri)
Dim workItemStore As WorkItemStore
workItemStore = tpc.GetService(Of WorkItemStore)()
Dim queryResults As WorkItemCollection
queryResults = workItemStore.Query(“
Select [State], [Title]
From WorkItems
Where [Work Item Type] = ‘User Story’
Order By [State] Asc, [Changed Date] Desc”)
主题内容
必需的权限
查询将返回您有 查看工作项 或 查看此节点中的工作项 权限的那些工作项。通常,这些授予 Readers (访问者) 的成员,并且每个团队的 参与者 机组。有关更多信息,请参见Team Foundation Server 权限。
提示 |
---|
使用 团队资源管理器,若要测试工作项查询语言的详细信息,请创建查询,然后将其保存为 .wiql 文件。重命名文件使用扩展名为 .xml 并打开它们在 Visual Studio。查找 wiql 元素查看每个查询如何使用工作项查询语言表示。 |
查询语言
工作项查询语言有五部分。
Select [State], [Title]
From WorkItems
Where [Work Item Type] = 'User Story'
Order By [State] Asc, [Changed Date] Desc
AsOf '6/15/2010'
Select [State], [Title] |
标识值在每 WorkItem 将设置由该查询返回的每 Field。可以指定显示名称或字段的引用名称。必须使用括号 ([]),如果该名称包含空白或句点。 |
From WorkItems |
指示是否希望查询查找工作项或链接工作项。
|
Where [Work Item Type] = 'User Story' |
为查询指定筛选条件。有关更多信息,请参见本主题后面的WHERE 子句。 |
Order By [State] Asc, [Changed Date] Desc |
(可选) 指定排序查询返回的 WorkItemCollection。 |
AsOf '6/15/2010' |
(可选) 若要指示筛选器将应用的日期或时间点指定一个历史查询。例如,此查询返回在 2010 年六月 15 日存在的所有用户情景。
说明
在 Visual Studio 的查询生成器无法创建 AsOf 查询。如果您使用 Visual Studio 创建包含 AsOf 子句,然后的查询文件 (.wiq) 加载时,AsOf 子句被忽略。
|
WHERE 子句
子句为工作项的位置指定查询的筛选条件。查询只返回符合这些条件仅的工作项。下面的示例查询返回处于活动状态,并指派给您的用户情景。
Where [Work Item Type] = 'User Story'
AND [State] = ‘Active’
AND [Assigned to] = @Me
您可以控制逻辑运算符的计算顺序,如果使用括号来组合搜索条件。例如,返回或指派给您或您关闭,更改查询筛选器匹配以下示例的工作项:
Where [Work Item Type] = 'User Story'
AND [State] = ‘Active’
AND ( [Assigned to] = @Me
OR [Closed by] = @Me )
下表描述语法子句的位置:
语法 |
示例 |
|
---|---|---|
WHERE 子句 |
Where FilterCondition [Group|{LogicalOperator FilterCondition}] |
|
组 |
(FilterCondition LogicalOperator FilterCondition [LogicalOperator Filter Condition]…) |
([Assigned to] = @Me OR [Created by = @Me]) 逻辑分组的运算符是 AND 和 OR。 |
FilterCondition |
Field ComparisonOperator Value |
[Work Item Type] = ‘Help Topic’ 可以指定引用名称或字段的显示名称。如果该名称中包含空格或句点,则在方括号必须将它 ([])。 比较运算符在 比较运算符 中有描述。本主题。 对于该值,可以指定文本值 (“用户 Story) 或宏 (@Me)。 |
值 |
LiteralValue|Variable|Field |
'User Story' |
比较运算符
可以使用下表中列出的运算符指定字段必须如何与对应的值相关:
查询运算符 |
描述 |
字段的适用的类型 |
---|---|---|
= |
值匹配。 |
数字、文本、日期和树 |
<> |
不符合该值。 |
数字、文本、日期和树 |
> |
大于该值。 |
数字、文本和日期 |
< |
与该值小于。 |
数字、文本和日期 |
>= |
大于或等于该值。 |
数字、文本和日期 |
<= |
小于或等于该值。 |
数字、文本和日期 |
Contains |
包含字符串。 |
文本 |
不包含 |
不包含字符串。 |
文本 |
在 ... 中 |
与 set 逗号分隔的任何值。例如,[System.Id] In (100, 101, 102) 查找工作 ID 为 100,101 和 102 的项目中。 |
数字、文本、日期和树 |
在组中 |
是组的成员。组可以是 Team Foundation 组 ([Assigned to] In Group [Project]\Contributors) 或工作项类别,当将它与工作项类型字段时 ([Work Item Type] In Group Requirements)。有关类别组的信息,请参见定义类别以分组工作项类型。 |
文本 |
不在组中 |
不是组的成员。有关更多信息,请 In Group请参见中的项。 |
文本 |
曾是 |
匹配,如果字段已满足该值,因此,即使它更改为其他值。 |
文本和日期 |
其下 |
有关区域和迭代,如果匹配,工作项在该节点或它的任何一个子节点中。有关区域和迭代的信息,请参见 创建和修改区域和迭代。 |
树 |
不在其下 |
有关区域和迭代,如果匹配,工作项不在该节点或它的任何一个子节点中。 |
树 |
变量
您在查询中使用变量将用户输入或计算的值。使用 @variable,若要创建包含变量的查询,请创建占位符在查询字符串。然后通过名称和每个值的变量与查询方法使用 IDictionary的实现,这样,下面的示例演示
// Define a query that uses a variable for the type of work item.
string queryString = "Select [State], [Title] From WorkItems Where [Work Item Type] = @Type";
// Set up a dictionary to pass "User Story" as the value of the type variable.
Dictionary<string, string> variables = new Dictionary<string, string>();
variables.Add("Type", "User Story");
// Create and run the query.
Query query = new Query(workItemStore, queryString, variables);
WorkItemCollection results = query.RunQuery();
// Define a query that uses a variable for the type of work item.
Dim queryString As New StringBuilder("SELECT [State], [Title] FROM WorkItems WHERE [WorkItemtype] = @Type")
// Set up a dictionary to pass "User Story" as the value of a type variable.
Dim variables = New Dictionary(Of String, String)
variables.Add("Type", "User Story")
// Create and run the query.
Dim query As New Query(workItemStore, queryString, variables)
WorkItemCollection results = query.RunQuery()
您在查询中使用 @Me 或 @Today,但未提供值为这些变量。当这些变量将显示在查询,但没有通过关联的值。IDictionary 实现时,变量进行计算,如下表所述:
变量 |
用法 |
---|---|
@Me |
指示包含用户名的字段的当前用户。例如,则可查找您激活的工作项,如果指定 [Activated by] = @Me。 |
@Today |
指示当前日期。可以通过增加或减少天数来修改 @Today 变量。例如,可以查找上周激活的所有项,如果指定 [Activated Date] > @Today - 7。 |
文本值
当为每个字段指定值时,该值必须与该字段的数据类型。在 Team Foundation 的所有字段都具有下表中列出的数据类型之一:
数据类型 |
存储的数据 |
---|---|
DateTime |
一个 datetime 值所定义的是 SQL Server。默认情况下,查询中的日期时间值的工作项都将被视为具有日期精度。例如,在 + 任何 + 时间创建在 2010 年六月 1 日的日的工作项,将与筛选条件 [Created Date] = 6/1/2010。 有关更多信息,请参见 查询方法和查询对象 本主题和 Microsoft 网站上的以下页面:日期时间 (Transact-SQL). |
Double |
一个实数,如 0.2 或 3.5。 |
GUID |
表示 GUID 的字符串)。 |
HTML |
包含 HTML 的文本字符串。 |
Integer |
签名,如 0,1,2 或 34 的 32 位整数。 |
PlainText |
不能超过 255 个字符的非格式化文本字符串。 |
String |
包含 255 个字符的文本字符串。 |
TreePath |
分支树结构,如"区域或迭代。 |
查询工作项之间的链接
还可以使用查询来查找工作项之间的链接。在的条件子句可以应用于链接或于源或链接目标的所有工作项的位置。下表总结了这些类型的查询和只有查询之间的差异工作项:
工作项 |
工作项之间的链接 |
|
---|---|---|
FROM 子句 |
从工作项 |
从 WorkItemLinks |
WHERE 子句 |
[FieldName] = Value |
以下之一:
|
Mode |
以下之一:
|
|
返回 |
[ T:Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemCollection ] |
一个 WorkItemLinkInfo 数组。 |
下面的查询返回用户情景及其有效的子节点之间的链接。
SELECT [System.Id]
FROM WorkItemLinks
WHERE ([Source].[System.WorkItemType] = 'User Story')
And ([System.Links.LinkType] = 'Child')
And ([Target].[System.State] = 'Active')
mode(MustContain)
查询方法和查询对象
使用 WorkItemStore.Query 方法,可以为工作项查询。还可以标识的工作项数。通过使用 WorkItemStore.QueryCount 方法,满足一个查询,而无需返回所有工作项。
可以创建 Query 对象定义并运行查询。
string queryString = "Select [Title] From WorkItems Where [Work Item Type] = 'User Story'"
Query query = new Query(workItemStore, queryString);
int numWorkItems = query.RunCountQuery();
Console.WriteLine("The project collection has " + numWorkItems.ToString() + " user stories.");
Dim queryString As New StringBuilder("Select [Title] FROM WorkItems WHERE [WorkItemType] = 'User Story'"
Dim query As New Query(workItemStore, queryString)
Dim numWorkItems As Int
numWorkItems = query.RunCountQuery()
Console.Writeline("The project collection has " + numWorkItems.ToString() + " user stories.")
异步查询
使用 Query.BeginQuery 方法,可以运行查询异步。下面的示例运行查询异步并在一个非常短的超时时间后取消查询。
// Run the query asynchronously, and time out after 0.05 seconds.
ICancelableAsyncResult callback = query.BeginQuery();
callback.AsyncWaitHandle.WaitOne(50, false);
if (!callback.IsCompleted)
{
callback.Cancel();
Console.WriteLine("The query timed out");
}
else
{
WorkItemCollection nextResults = query.EndQuery(callback);
Console.WriteLine("The project collection has " + nextResults.Count.ToString() + " work items.");
}
Dim callback as ICancelableAsyncResult
callback = query.RunQuery()
callback.AsyncAWaitHandle.WaitOne(50, False)
If Not (callback.IsCompleted)
Then
callback.Cancel()
Console.Writeline("The query timed out")
Else
Dim nextResults As WorkItemCollection = query.EndQuery(callback)
Console.Writeline("The project collection has " + nextResults.Count.ToString() + " work items.")
End If
字段值分页
查询返回的 WorkItemCollection 包含以下字段的值:
ID
(发布)
AreaID
IterationID
WorkItemType
在 select 子句指定字段的值在页返回。
说明 |
---|
默认情况下,每页包含 50 个工作项的选定的字段。使用 WorkItemCollection.PageSize,可以调整页的大小。 |
您可以最大限度地减少到服务器的往返行程通过选择您的代码的所有字段。下面的代码进行查询的一个往返行程和一个往返行程都会返回新的页访问标题的页。
WorkItemCollection results = WorkItemStore.Query(
"SELECT Title FROM Workitems WHERE (ID < 1000)");
foreach (WorkItem item in results)
{
Console.WriteLine(item.Fields["Title"].Value);
}
如果您的代码访问在 select 子句中指定的字段,该字段添加到设置被调用的字段。另一个往返行程执行刷新该页包含该字段的值。
查询语法 (EBNF)
扩展 backus-naur 形式 (bnf) (EBNF) 是在紧凑、明确的方式描述语言语法的元语言。此代码块使用 EBNF 描述工作项查询语言 (WIQL) 语法。
如果您不熟悉 EBNF,请参见 WIQL 的可选说明。Syntax for the Work Item Query Language的。
<select> ::= <flat-select> | <one-hop-select> | <recursive-select>
<flat-select> ::= select <field list>
from workitems
[ where <expression> ]
[ order by <order by field list> ]
[ asof <datetime> ]
<one-hop-select> ::= select <field list>
from workitemlinks
[ where <one-hop-link-expression> <source-expression> <target-expression> ]
[ order by <source-target order by field list> ]
[ asof <datetime> ]
mode( mustcontain | maycontain | doesnotcontain )
<recursive-select> ::= select <field list>
from workitemlinks
where <recursive-link-expression> [ and <source-expression> <target-expression> ]
mode ( recursive | returnmatchingchildren )
<expression> ::= <expression4>
<expression4> ::= <expression3> [ or <expression4> ]
<expression3> ::= <expression2> [ and <expression3> ]
<expression2> ::= {[ not | ever ] <expression2> }
| <expression1>
<expression1> ::= <conditional expression>
<conditional expression> ::= { '(' <expression> ')' } | <field reference name> <conditional operator> <value> | <field reference name> [not] in '(' <value list> ')'
<value> ::= <number>
| <string>
| <datetime>
<value list> ::= <value> [ ',' <value list> ]
<conditional operator> ::= { '=' | '<>' | '<' | '<=' | '>' | '>=' }
| { [ever] [not] { like | under }}
<link operator> ::= '=' | '<>'
<field list> ::= <field name> [ ',' <field list> ]
<order by field list> ::= <order by field> [ ',' <order by field list> ]
<source-target order by field list> ::= [ <source> |<target> ] <order by field> [ ',' <source-target order by field list> ]
<order by field> ::= <field name> [ 'asc' | 'desc' ]
<number> ::= [ '-' ] <digit>* [ '.' [ <digit>* ]] [ { e | E } [ '-' ] <digit>* ]
<string> ::= { ''' { <anychar except '''> | '''' }* ''' }
| { '"' { <anychar except '"'> | '""' }* '"' }
<datetime> ::= <string>
<source> ::= '[source].'
<target> ::= '[target].'
<one-hop-link-expression> ::= <one-hop-link-expression4> | ''
<one-hop-link-expression4> ::= <one-hop-link-expression3> [ or <one-hop-link-expression4> ]
<one-hop-link-expression3> ::= <one-hop-link-expression2> [ and <one-hop-link-expression3> ]
<one-hop-link-expression2> ::= {[ not | ever ] <one-hop-link-expression2>}
| <one-hop-link-expression1>
<one-hop-link-expression1> ::= <conditional-link-expression>
<conditional-link-expression> ::= { '(' <one-hop-link-expression> ')' } | <linktype-field> <link operator> <linktype-name><linktype-direction> | <linktype-field> [not] 'in (' <linktype list> ')'
<recursive-link-expression> ::= <linktype-field> '=' <linktype-name>'-forward'
<linktype list> ::= <linktype-name><linktype-direction> [, <linktype-name><linktype-direction>]
<linktype-direction> ::= '-forward' | '-reverse'
<source-expression> ::= <source-expression4> | ''
<source-expression4> ::= <source-expression3> [ or <source-expression4> ]
<source-expression3> ::= <source-expression2> [ and <source-expression3> ]
<source-expression2> ::= {[ not | ever ] <source-expression2> }
| <source-expression1>
<source-expression1> ::= <conditional-source-expression>
<conditional-source-expression> ::= { '(' <source-expression> ')' } | <source><field reference name> <conditional operator> <value> | <source><field reference name> [not] in '(' <value list> ')'
<target-expression> ::= <target-expression4> | ''
<target-expression4> ::= <target-expression3> [ or <target-expression4> ]
<target-expression3> ::= <target-expression2> [ and <target-expression3> ]
<target-expression2> ::= {[ not | ever ] <target-expression2> }
| <target-expression1>
<target-expression1> ::= <conditional-target-expression>
<conditional-target-expression> ::= { '(' <target-expression> ')' } | <target><field reference name> <conditional operator> <value> | <target><field reference name> [not] in '(' <value list> ')'
<linktype-field> ::= '[System.Links.LinkType] = '
<select> ::= select <field list>
from workitems
[ where <expression> ]
[ order by <order by field list> ]
[ asof <datetime> ]
<expression> ::= <expression4>
<expression4> ::= <expression3> [ or <expression4> ]
<expression3> ::= <expression2> [ and <expression3> ]
<expression2> ::= {[ not | ever ] <expression2> }
| <expression1>
<expression1> ::= <conditional expression>
<conditional expression> ::= { '(' <expression> ')' } | <field reference name> <conditional operator> <value> | <field reference name> [not] in '(' <value list> ')'
<value> ::= <number>
| <string>
| <datetime>
<value list> ::= <value> [ ',' <value list> ]
<conditional operator> ::= { '=' | '<>' | '<' | '<=' | '>' | '>=' }
| { [ever] [not] { like | under }}
<field list> ::= <field name> [ ',' <field list> ]
<order by field list> ::= <field name> [ asc | desc ] [ ',' <order by field list> ]
<number> ::= [ '-' ] <digit>* [ '.' [ <digit>* ]] [ { e | E } [ '-' ] <digit>* ]
<string> ::= { ''' { <anychar except '''> | '''' }* ''' }
| { '"' { <anychar except '"'> | '""' }* '"' }
<datetime> ::= <string> Insert section body here.