2009-10-13 8 views
11

Próbuję napisać kwerendę CAML, która wykonuje wobec określonego SPList, zakres do określonego folderu, rekursywne od tego punktu i zwraca wszystkie ListItems (które spełniają kryteria) i foldery .Kwerenda CAML, która zawiera foldery w zestawie wyników

Oto kod dla zapytania, które wydaje się, że powinna pracować (sformatowany dla czytelności):

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(); 

Tak - to tylko zwraca ListItems - żadnych folderów.

Jeśli usunę inne warunki z kwerendy, tylko pozostawiając FSObjType=1, otrzymuję wyjątek COM "Nie można wykonać tej czynności. Proszę spróbuj ponownie."

Jeśli następnie usunę ViewFields, pozostawiając tylko Scope=RecursiveAll i FSObjType=1, otrzymam pusty zestaw wyników.

+0

Czy kiedykolwiek rozwiązałeś to? Mam ten sam problem i jeśli nie ma rozwiązania, będę musiał napisać funkcję rekursywną, aby to zrobić. – jeremcc

+0

@codeflunky niestety nie, nigdy nie działałem poprawnie. –

+0

@codeflunky, jeśli znajdziesz rozwiązanie, proszę opublikuj tutaj! –

Odpowiedz

5

Nie mam własnego obrazu do przetestowania, więc może będę musiał to później zmienić; ale myślę, że można spróbować

query.ViewAttributes = "Scope=\"Recursive\""; 

Odzyskiwanie elementów pozwoli Ci korzystać SPUtility.GetUrlDirectory(url) aby uzyskać ścieżkę folderu dla danej pozycji i analizowania hierarchii folderów stamtąd.

+1

"Rekurencyjne" przeszukuje foldery głęboko, ale nie zawiera obiektów folderów w zestawie wyników. Chciałbym uzyskać wszystkie informacje, których potrzebuję w trakcie jednej podróży w obie strony - dzięki temu dziesiątki wywołań API w górnej części zapytania jest mniej niż idealne. –

+0

Jeśli mogę zapytać, czy używasz tego jako dostawcy dla jakiegoś elementu interfejsu użytkownika, takiego jak widok drzewa, który może używać leniwego ładowania? Czy będziesz musiał wyciągnąć wszystko podczas jednego przejścia? – gn22

+0

@Gurdas wszystko musi zostać pobrane od razu –

1

Jeśli usunąć inne warunki z zapytaniem, tylko pozostawiając FSObjType = 1, otrzymuję wyjątek COM „Nie można wykonać tę czynność. Spróbuj ponownie.”

Czy usunąłeś znaczniki <Or>, gdy to zrobiłeś? Jeśli nie, nie będzie działać poprawnie.

Bez względu na to, nie rozwiąże to problemu. Czy próbowałeś pozostawić puste zapytanie? Czy to coś zwraca?

Pracowałem nad czymś podobnym i wpadłem na numer issue, być może jest to trochę podobne.

+0

Tak, wszystkie moje zapytania CAML są generowane programowo, aby uniknąć błędów składniowych, takich jak zbędne ''. To nie jest problem z składnią. –

+0

Czy otrzymasz zestaw wyników, jeśli pozostawisz puste zapytanie? – Mark

+0

Przepraszam za spóźnioną odpowiedź. Dostaję zestaw wyników przedmiotów tylko wtedy, gdy usunę wszystkie warunki. –

5

Można spróbować opierając zapytanie Caml na zawartość folderu Wpisz zamiast

<FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value> 

utrzymując

Query.ViewAttributes = "Scope=\"RecursiveAll\""; 
+0

Próbowałem tego z tymi samymi wynikami. –

+0

To zadziałało dla mnie. Byłem w stanie zapytać o typ zawartości folderu dla folderów zagnieżdżonych w folderach przy pomocy RecursiveAll. –

3

I został rozwiązany to oddanie:

<QueryOptions> 
<IncludeAttachmentUrls>True</IncludeAttachmentUrls> 
<Folder/> </QueryOptions> 

jako opcja zapytania

znalazłem moje pytanie o tym na przepełnienie stosu:

How can I iterate recursively though a sharepoint list using webservices?

+0

Interesujące ... Spróbuję. Co ma zrobić pusty tag folderu? –

+0

Powinno to zwrócić folder, ale nie pamiętam już teraz. SPList jest bardzo skomplikowanym i niejasnym serwisem internetowym, czasem jest magiczny ... :) Jeśli to nie zadziała, sprawdzę tutaj moje dokumenty. –

1

To wciąż wydaje się problemu w SP 2010. Oto kod obejście, które będą działać na rok 2007 lub 2010, w oparciu o this MSDN Forums post że korzysta z usług internetowych:

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); 
} 
14

Wszyscy są blisko, ale nie do końca.

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 
} 

Przede wszystkim, za pomocą tego FieldRef jest źle:

<FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value> 

ponieważ typ zawartości folderu mogą być dziedziczone. Dlatego trzeba porównać z identyfikatorem typu zawartości, tak:

<Where> 
    <BeginsWith> 
    <FieldRef Name='ContentTypeId' /> 
    <Value Type='ContentTypeId'>0x0120</Value> 
    </BeginsWith> 
</Where> 

A potem ustawić widok przypisują zakres do RecursiveAll

<View Scope='RecursiveAll'>...</View> 

To powinno powrócić dowolny element, którego treść typ dziedziczy z folderu (0x0120)

+0

Dziękuję bardzo za Scope = 'RecursiveAll' –

0
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());  
    } 
Powiązane problemy