2011-06-01 8 views
27

Estoy trabajando en el código de prueba de concepto para generar CAML dinámicamente en base a palabras clave proporcionadas a un servicio web de búsqueda altamente específico que estoy escribiendo. No estoy utilizando el servicio web de búsqueda proporcionado por SharePoint para esta prueba. Ya lo hice por lo que estoy tratando de lograr. De toda mi investigación, no puedo encontrar un ejemplo cercano de lo que estoy tratando de lograr, que es verificar múltiples campos para valores múltiples. Sí, ya he consultado SO por mi respuesta, incluida esta: Need help on building CAML Query.Consulta CAML con AND anidados y OR para campos múltiples

Dicho esto, si es posible, ¿cómo se puede escribir la siguiente consulta SQL en CAML?

SELECT FirstName, LastName, Description, Profile 
FROM SomeFakeTable 
WHERE (FirstName = 'John' OR LastName = 'John' OR Description = 'John' OR Profile='John') 
    AND (FirstName = 'Doe' OR LastName = 'Doe' OR Description = 'Doe' OR Profile='Doe') 
    AND (FirstName = '123' OR LastName = '123' OR Description = '123' OR Profile='123') 

Respuesta

50

Dado que no está permitido poner más de dos condiciones en un grupo de condiciones (Y | O) tiene que crear un grupo adicional anidado (MSDN). La expresión A AND B AND C se ve así:

<And> 
    A 
    <And> 
     B 
     C 
    </And> 
</And> 

Su SQL como muestra traducida a CAML (esperemos que se combina con etiquetas XML;)):

<Where> 
    <And> 
     <Or> 
      <Eq> 
       <FieldRef Name='FirstName' /> 
       <Value Type='Text'>John</Value> 
      </Eq> 
      <Or> 
       <Eq> 
        <FieldRef Name='LastName' /> 
        <Value Type='Text'>John</Value> 
       </Eq> 
       <Eq> 
        <FieldRef Name='Profile' /> 
        <Value Type='Text'>John</Value> 
       </Eq> 
      </Or> 
     </Or> 
     <And>  
      <Or> 
       <Eq> 
        <FieldRef Name='FirstName' /> 
        <Value Type='Text'>Doe</Value> 
       </Eq> 
       <Or> 
        <Eq> 
         <FieldRef Name='LastName' /> 
         <Value Type='Text'>Doe</Value> 
        </Eq> 
        <Eq> 
         <FieldRef Name='Profile' /> 
         <Value Type='Text'>Doe</Value> 
        </Eq> 
       </Or> 
      </Or> 
      <Or> 
       <Eq> 
        <FieldRef Name='FirstName' /> 
        <Value Type='Text'>123</Value> 
       </Eq> 
       <Or> 
        <Eq> 
         <FieldRef Name='LastName' /> 
         <Value Type='Text'>123</Value> 
        </Eq> 
        <Eq> 
         <FieldRef Name='Profile' /> 
         <Value Type='Text'>123</Value> 
        </Eq> 
       </Or> 
      </Or> 
     </And> 
    </And> 
</Where> 
+0

¡Gracias, Jason! Volví a visitar mi pregunta para dar una respuesta, porque lo descubrí por mi cuenta. Sin embargo, estoy tan contento de ver que su respuesta coincide con mis resultados y muy agradecida de que se haya tomado el tiempo para ayudarnos a mí y a otros usuarios de SO. – Alban

+0

Gracias por su publicación. Su XML de ejemplo ofrece una buena manera de verificar la sintaxis anidada. Lo usé para llegar a este método de generar un [equivalente al operador In] (http://stackoverflow.com/questions/11198161/caml-in-operator-equivalent-for-sharepoint-services-3-sharepoint- 2007) – xr280xr

0

Usted puede tratar de U2U Generador de consultas http://www.u2u.net/res/Tools/CamlQueryBuilder.aspx puede utilizar su API y U2U.SharePoint.CAML.Server.dll U2U.SharePoint.CAML.Client.dll

no hizo uso de ellos, pero yo Estoy seguro de que te ayudará a lograr tu tarea.

+13

No debe publicar una solución de aquí a menos que sepa que puede proporcionar el resultado requerido. Usar la herramienta U2U es un gran ahorro de tiempo, pero debe proporcionar un ejemplo de trabajo del código que genera. –

0

Este código generará dinámicamente la expresión para usted con el anidado cláusulas. Tengo un escenario donde el número de "O" era desconocido, entonces estoy usando el siguiente. Uso:

 private static void Main(string[] args) 
     { 
      var query = new PropertyString(@"<Query><Where>{{WhereClauses}}</Where></Query>"); 
      var whereClause = 
       new PropertyString(@"<Eq><FieldRef Name='ID'/><Value Type='Counter'>{{NestClauseValue}}</Value></Eq>"); 
      var andClause = new PropertyString("<Or>{{FirstExpression}}{{SecondExpression}}</Or>"); 

      string[] values = {"1", "2", "3", "4", "5", "6"}; 

      query["WhereClauses"] = NestEq(whereClause, andClause, values); 

      Console.WriteLine(query); 
     } 

Y aquí está el código:

private static string MakeExpression(PropertyString nestClause, string value) 
     { 
      var expr = nestClause.New(); 
      expr["NestClauseValue"] = value; 
      return expr.ToString(); 
     } 

     /// <summary> 
     /// Recursively nests the clause with the nesting expression, until nestClauseValue is empty. 
     /// </summary> 
     /// <param name="whereClause"> A property string in the following format: <Eq><FieldRef Name='Title'/><Value Type='Text'>{{NestClauseValue}}</Value></Eq>"; </param> 
     /// <param name="nestingExpression"> A property string in the following format: <And>{{FirstExpression}}{{SecondExpression}}</And> </param> 
     /// <param name="nestClauseValues">A string value which NestClauseValue will be filled in with.</param> 
     public static string NestEq(PropertyString whereClause, PropertyString nestingExpression, string[] nestClauseValues, int pos=0) 
     { 
      if (pos > nestClauseValues.Length) 
      { 
       return ""; 
      } 

      if (nestClauseValues.Length == 1) 
      { 
       return MakeExpression(whereClause, nestClauseValues[0]); 
      } 

      var expr = nestingExpression.New(); 
      if (pos == nestClauseValues.Length - 2) 
      { 
       expr["FirstExpression"] = MakeExpression(whereClause, nestClauseValues[pos]); 
       expr["SecondExpression"] = MakeExpression(whereClause, nestClauseValues[pos + 1]); 
       return expr.ToString(); 
      } 
      else 
      { 
       expr["FirstExpression"] = MakeExpression(whereClause, nestClauseValues[pos]); 
       expr["SecondExpression"] = NestEq(whereClause, nestingExpression, nestClauseValues, pos + 1); 
       return expr.ToString(); 
      } 
     } 






      public class PropertyString 
    { 
     private string _propStr; 

     public PropertyString New() 
     { 
      return new PropertyString(_propStr); 
     } 

     public PropertyString(string propStr) 
     { 
      _propStr = propStr; 
      _properties = new Dictionary<string, string>(); 
     } 

     private Dictionary<string, string> _properties; 
     public string this[string key] 
     { 
      get 
      { 
       return _properties.ContainsKey(key) ? _properties[key] : string.Empty; 
      } 
      set 
      { 
       if (_properties.ContainsKey(key)) 
       { 
        _properties[key] = value; 
       } 
       else 
       { 
        _properties.Add(key, value); 
       } 
      } 
     } 



     /// <summary> 
     /// Replaces properties in the format {{propertyName}} in the source string with values from KeyValuePairPropertiesDictionarysupplied dictionary.nce you've set a property it's replaced in the string and you 
     /// </summary> 
     /// <param name="originalStr"></param> 
     /// <param name="keyValuePairPropertiesDictionary"></param> 
     /// <returns></returns> 
     public override string ToString() 
     { 
      string modifiedStr = _propStr; 
      foreach (var keyvaluePair in _properties) 
      { 
       modifiedStr = modifiedStr.Replace("{{" + keyvaluePair.Key + "}}", keyvaluePair.Value); 
      } 

      return modifiedStr; 
     } 
    } 
+0

¿Ha buscado el límite de consulta anidado o caml? Puede causar problemas en este código. –

Cuestiones relacionadas