2009-12-11 7 views
11

Existe-t-il une "bonne" façon de créer une requête CAML pour SharePoint qui fait quelque chose comme ça?Équivalent SQL IN dans CAML

SELECT * 
FROM table 
WHERE Id IN (3, 12, ...) 

Ou suis-je coincé avec un cauchemar de <Or> imbriqués nœuds?


EDIT: Cela a été ma solution pour générer les noeuds <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); 
} 

Utilisation:

int[] ids = new int[] { 1, 2, 4, 5 }; 
string query = string.Format("<Where>{0}</Where>", CamlIn("SomeColumn", "Number", ids)); 

Sortie:

<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> 

fait également cette surcharge pour travailler avec les champs de recherche un peu plus facile

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

Répondre

5

FullTextSqlQuery

Il est possible de rechercher MOSS en utilisant des instructions SQL, en utilisant la classe FullTextSqlQuery. Je n'ai aucune expérience de l'utilisation de cette classe personnellement. Ces articles peuvent être utiles:

YACAMLQT

Sinon, il y a aussi YACAMLQT (Yet Another CAML Query Tool) qui vous permet de créer des requêtes SharePoint CAML utilisant un T-SQL syntaxe.

LINQ to SharePoint

Si vous êtes à la vitesse avec LINQ, le LINQ to SharePoint project fournit un outil pour interroger des listes SharePoint en utilisant la syntaxe LINQ. Veuillez noter que cet outil est toujours en phase de test alpha, il n'est donc peut-être pas prêt pour la production.

U2U CAML Query Builder

Si vous travaillez avec des requêtes CAML, je vous conseille d'utiliser l'outil U2U CAML Query Builder for SharePoint (2003 et 2007) pour construire vos requêtes CAML. L'outil vous permet de construire votre chaîne de requête, et de l'exécuter par rapport à la liste cible, en utilisant une interface pointer-cliquer, comme indiqué ci-dessous.

U2U CAML Query Builder for SharePoint in action http://www.u2u.net/res/Images/Tools/CQB/buildwhereclause6.png

des quatre méthodes, je peux recommander le U2U CAML Query Builder, ayant utilisé presque tous les jours au cours des 6 derniers mois ci-dessus. Il semble également être l'outil CAML le plus largement utilisé dans la communauté SharePoint.

Notez, si vous construisez les requêtes CAML dans le code, alors je vous recommande de jeter un oeil au CAML.NET project sur CodePlex, qui fournit "un ensemble de.. outils de langue NET pour la création de composants de requête CAML dynamiques, réutilisables »

+0

Ne connaissait pas CAML.NET. Peut-être besoin d'utiliser cela dans le futur. J'ai fait quelque chose de similaire avec XElements pour générer les ''. – Chris

23

Pour ceux qui utilisent Sharepoint 2010, il y a un élément IN disponible:

http://msdn.microsoft.com/en-us/library/ff625761.aspx

Voici un exemple de travail:

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