web-dev-qa-db-fra.com

Requête CAML avec AND et OR imbriqués pour plusieurs champs

Je travaille sur un code de preuve de concept pour générer dynamiquement CAML sur la base de mots clés fournis à un service Web de recherche hautement spécifique que j'écris. Je n'utilise pas le service Web de recherche fourni par SharePoint pour cette preuve. Je l'ai déjà fait pour ce que j'essaie de réaliser. De toutes mes recherches, je ne peux pas trouver un exemple proche de ce que j'essaie de réaliser, qui est de vérifier plusieurs champs pour plusieurs valeurs. Oui, j'ai regardé SO déjà pour ma réponse, y compris celle-ci: Besoin d'aide pour construire la requête CAML .

Cela dit, si c'est possible, comment la requête de type SQL suivante peut-elle être écrite 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')
28
Alban

Comme vous n'êtes pas autorisé à mettre plus de deux conditions dans un groupe de conditions (Et | Ou), vous devez créer un groupe imbriqué supplémentaire ( MSDN ). L'expression A AND B AND C ressemble à ça:

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

Votre exemple SQL comme traduit en CAML (si tout va bien avec les balises XML correspondantes;)):

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

Ce code générera dynamiquement l'expression pour vous avec les clauses imbriquées. J'ai un scénario où le nombre de "OU" était inconnu, donc j'utilise le ci-dessous. Usage:

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

Et voici le code:

   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
David

Vous pouvez essayer U2U Query Builder http://www.u2u.net/res/Tools/CamlQueryBuilder.aspx vous pouvez utiliser leur API U2U.SharePoint.CAML.Server.dll et U2U.SharePoint.CAML .Client.dll

Je ne les ai pas utilisés mais je suis sûr que cela vous aidera à accomplir votre tâche.

0
Ahmed Magdy