是否有一种“好的”方法来为SharePoint创建这样的类似的CAML查询?
SELECT *
FROM table
WHERE Id IN (3, 12, ...)
还是我陷入了嵌套的<Or>
节点的噩梦?
编辑:这是我生成<Or>
节点的解决方案。
/// Simulates a SQL 'Where In' clause in CAML
/// </summary>
/// <param name="columnType">Specifies the data type for the value contained by the field.</param>
/// <returns>Nested 'Or' elements portion of CAML query</returns>
public static string CamlIn<T>(string internalFieldName, string columnType, T[] values)
{
XDocument doc = new XDocument();
XElement prev = null;
int index = 0;
while (index < values.Length)
{
XElement element =
new XElement("Or",
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName)),
new XElement("Value",
new XAttribute("Type", columnType),
values[index++].ToString())));
if (index == values.Length - 1)
{
element.AddFirst(
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName)),
new XElement("Value",
new XAttribute("Type", columnType),
values[index++].ToString())));
}
if (prev != null)
prev.AddFirst(element);
else
doc.Add(element);
prev = element;
}
return doc.ToString(SaveOptions.DisableFormatting);
}
用法:
int[] ids = new int[] { 1, 2, 4, 5 };
string query = string.Format("<Where>{0}</Where>", CamlIn("SomeColumn", "Number", ids));
输出:
<Where>
<Or>
<Or>
<Or>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">5</Value>
</Eq>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">4</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">2</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">1</Value>
</Eq>
</Or>
</Where>
这也使得使用查找字段更容易
/// <summary>
/// Simulates a SQL 'Where In' clause in CAML
/// </summary>
/// <param name="lookupId">Specify whether to use the Lookup column's Id or Value.</param>
/// <returns>Nested 'Or' elements portion of CAML query</returns>
public static string CamlIn<T>(string internalFieldName, bool lookupId, T[] values)
{
XDocument doc = new XDocument();
XElement prev = null;
int index = 0;
while (index < values.Length)
{
XElement element =
new XElement("Or",
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName),
lookupId ? new XAttribute("LookupId", "TRUE") : null),
new XElement("Value",
new XAttribute("Type", "Lookup"),
values[index++].ToString())));
if (index == values.Length - 1)
{
element.AddFirst(
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName),
lookupId ? new XAttribute("LookupId", "TRUE") : null),
new XElement("Value",
new XAttribute("Type", "Lookup"),
values[index++].ToString())));
}
if (prev != null)
prev.AddFirst(element);
else
doc.Add(element);
prev = element;
}
if (values.Length == 1)
{
XElement newRoot = doc.Descendants("Eq").Single();
doc.RemoveNodes();
doc.Add(newRoot);
}
return doc.ToString(SaveOptions.DisableFormatting);
}
不,你需要处理嵌套的OR
标签;这些是supported query instructions on CAML
也许CAML.NET可以帮助您完成任务。
对于使用Sharepoint 2010的用户,可以使用IN元素:
http://msdn.microsoft.com/en-us/library/ff625761.aspx
这是一个有效的例子:
SPQuery locationsQuery = new SPQuery();
locationsQuery.Query = string.Concat("<Where>",
"<In>",
"<FieldRef Name='ID' />",
"<Values>",
"<Value Type='Number'>6</Value>",
"<Value Type='Number'>7</Value>",
"<Value Type='Number'>8</Value>",
"</Values>",
"</In>",
"</Where>");
FullTextSqlQuery
可以使用FullTextSqlQuery类使用SQL语句搜索MOSS。我没有亲自使用这门课程的经验。这些文章可能有用:
YATSAMLYAT
或者,还有YACAMLQT (Yet Another CAML Query Tool),它允许您使用T-SQL语法创建SharePoint CAML查询。
LINQ to SharePoint
如果您熟悉LINQ,那么LINQ to SharePoint project提供了一个使用LINQ语法查询SharePoint列表的工具。请注意,此工具仍处于alpha测试阶段,因此可能无法生产。
U2U CAML查询生成器
如果您正在使用CAML查询,我建议使用U2U CAML Query Builder for SharePoint(2003和2007)工具来构建您的CAML查询。该工具允许您使用点击式界面构建查询字符串并对目标列表执行它,如下所示。
(来源:u2u.net)
在上述四种方法中,我可以推荐U2U CAML查询生成器,在过去的6个月中几乎每天都使用它。它似乎也是SharePoint社区中使用最广泛的CAML工具。
注意,如果您在代码中构建CAML查询,那么我建议您查看CAML.NET project上的CodePlex,它提供了“一组基于.NET语言的工具,用于创建动态,可重用的CAML查询组件”。
我遇到了类似的事情,最终不得不创建一个递归算法来生成嵌套的OR结构。这是我的算法
var DynamicQuery = '<Query><Where>{{DYNAMICSTRING}}</Where></Query>';
var OneOR = '<Or><Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq>{{DYNAMICSTRING}}</Or>';
var TwoOr = '<Or><Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq><Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq></Or>';
var OnlyEq = '<Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq>';
function generateAdvancedInQuery(x){
if(x.length == 1)
return OnlyEq.replace('{{SearchValue}}',x[0]);
else if(x.length == 2)
return TwoOr.replace('{{SearchValue}}',x[0]).replace('{{SearchValue}}',x[1]);
else
return OneOR.replace('{{SearchValue}}',x[x.length-1]).replace('{{DYNAMICSTRING}}',generateAdvancedInQuery(x.splice(0,x.length-1) ) );
}
x = ['438753234098792','438753234098793','438753234098794','438753234098795','438753234098796','438753234098797','438753234098798'];
var Caml = DynamicQuery.replace('{{DYNAMICSTRING}}',generateAdvancedInQuery(x) )
这会生成XML caml查询
<Query>
<Where>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098798</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098797</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098796</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098795</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098794</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098792</Value>
</Eq>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098793</Value>
</Eq>
</Or>
</Or>
</Or>
</Or>
</Or>
</Or>
</Where>
</Query>