Запрос CAML, содержащий папки в наборе результатов
Я пытаюсь написать запрос CAML, который выполняется против определенного SPList, привязанный к определенной папке, рекурсивный с этой точки, и возвращает все ListItems (которые соответствуют критериям) и Folders.
Здесь код для запроса, который, похоже, должен работать (отформатирован для удобочитаемости):
SPQuery query = new SPQuery();
query.Query = "
<Where>
<Or>
<Contains>
<FieldRef Name=\"FileRef\" />
<Value Type=\"Text\">foo</Value>
</Contains>
<Eq>
<FieldRef Name=\"FSObjType\" />
<Value Type=\"Lookup\">1</Value>
</Eq>
</Or>
</Where>";
query.ViewFields = "
<FieldRef Name=\"CustomField1\" Nullable=\"TRUE\" />
<FieldRef Name=\"CustomField2\" Nullable=\"TRUE\" />
<FieldRef Name=\"CustomField3\" Nullable=\"TRUE\" />
";
query.RowLimit = 500;
query.ViewAttributes = "Scope=\"RecursiveAll\"";
query.Folder = startingFolder;
DataTable dt = myList.GetItems(query).GetDataTable();
Итак - это возвращает только список ListItems - без папок.
Если я удалю другие условия из запроса, оставив только FSObjType=1
, я получаю исключение COM "Не могу завершить это действие. Повторите попытку".
Если я затем удалю ViewFields, оставив только Scope=RecursiveAll
и FSObjType=1
, я получаю пустой результат.
Ответы
Ответ 1
Все близки, но не совсем правильно.
using (SPSite site = new SPSite("http://server/site"))
{
SPWeb web = site.RootWeb; // See disposal guidance http://blogs.msdn.com/b/rogerla/archive/2008/10/04/updated-spsite-rootweb-dispose-guidance.aspx
SPQuery query = new SPQuery();
query.Query = @"
<Where>
<BeginsWith>
<FieldRef Name='ContentTypeId' />
<Value Type='ContentTypeId'>0x0120</Value>
</BeginsWith>
</Where>";
query.ViewAttributes = "Scope='RecursiveAll'";
SPList list = web.Lists[listId];
SPListItemCollection items = list.GetItems(query);
// Do stuff with your folders
}
Прежде всего, использование этого FieldRef неверно:
<FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value>
потому что тип содержимого папки может быть унаследован. Поэтому вам нужно сравнить с ID типа контента, например:
<Where>
<BeginsWith>
<FieldRef Name='ContentTypeId' />
<Value Type='ContentTypeId'>0x0120</Value>
</BeginsWith>
</Where>
И затем установите атрибут вида Scope на RecursiveAll
<View Scope='RecursiveAll'>...</View>
Это должно возвращать любой элемент, тип содержимого которого наследуется от папки (0x0120)
Ответ 2
У меня нет моего образа для тестирования, поэтому мне, возможно, придется его пересмотреть позже; но я думаю, вы могли попробовать
query.ViewAttributes = "Scope=\"Recursive\"";
Извлечение элементов позволит вам использовать SPUtility.GetUrlDirectory(url)
, чтобы получить путь к папке для данного элемента, и проанализируйте иерархию папок оттуда.
Ответ 3
Вместо этого вы можете попробовать создать свой запрос caml в типе содержимого папки,
<FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value>
сохраняя
Query.ViewAttributes = "Scope=\"RecursiveAll\"";
Ответ 4
Я решил это поставить:
<QueryOptions>
<IncludeAttachmentUrls>True</IncludeAttachmentUrls>
<Folder/> </QueryOptions>
В качестве опции запроса
Я нашел свой вопрос об этом при переполнении стека:
Как я могу рекурсивно перебирать список sharepoint с помощью webservices?
Ответ 5
Если я удалю другие условия из запроса, оставив только FSObjType = 1, я получаю исключение COM "Не могу завершить это действие. Повторите попытку".
Удалили ли теги <Or>
, когда вы это сделали? Если нет, это не будет работать правильно.
Независимо, это не решает вашу проблему. Вы пробовали оставить запрос пустым? Он что-то возвращает?
Я работал над чем-то похожим и столкнулся с проблемой , возможно, это несколько связано.
Ответ 6
Это все еще кажется проблемой в SP 2010. Здесь код обхода, который будет работать в 2007 или 2010 году, на основе этого форума MSDN использует веб-службы:
private static SPListItem RecurseIntoFolders(SPList list, SPFolder parentFolder, string fileReference)
{
var query = new SPQuery
{
Query = "<Where>" +
"<Eq><FieldRef Name='FSObjType'/><Value Type='Lookup'>1</Value></Eq>" +
"</Where>",
ViewFields = String.Format("<FieldRef Name='{0}' />", FileReferenceInternalFieldName),
ViewAttributes = "Scope='RecursiveAll'",
Folder = parentFolder
};
var items = list.GetItems(query);
if (items.Count == 0)
return null;
foreach (SPListItem item in items)
{
parentFolder = item.Folder;
// TODO: Any other checking that this is the item we want
return item;
}
return RecurseIntoFolders(list, parentFolder, fileReference);
}
Ответ 7
static string GetParentFolder(SPListItem itemToFind, SPFolder folder)
{
SPQuery query = new SPQuery();
// query.Query = "<OrderBy><FieldRef Name='Title'/></OrderBy>";
query.Query = "<Where><Eq><FieldRef Name=\"ID\"/><Value Type=\"Integer\">"+ itemToFind.ID +"</Value></Eq></Where>";
query.Folder = folder;
query.ViewAttributes = "Scope=\"Recursive\"";
SPListItemCollection items = itemToFind.ParentList.GetItems(query);
int intpartentFolderID=0 ;
if (items.Count > 0)
{
foreach (SPListItem item in items)
{
SPFile f = item.Web.GetFile(item.Url);
string test11 = f.ParentFolder.Name;
intpartentFolderID = f.ParentFolder.Item.ID;
//string test1 = item.File.ParentFolder.Name;
return (intpartentFolderID.ToString());
}
}
return (intpartentFolderID.ToString());
}