SharePoint 2007 : Extension Method (DeleteAllItems)

Après vous avoir parlé de ce que l'on pouvait faire avec les extensions de méthode et un peu de "réflection", j'aimerais vous montrer aujourd'hui une autre combinaison très intéressante :

Les extensions de méthode et ProcessBatchData : Voici un exemple avec une extension de méthode qui supprime tout les éléments d'une liste ou d'un bibliothèque de document.

Ci-dessous, je compare deux méthodes, la suppression classique d'éléments dans une liste et la suppression en utilisant l'extension de méthode DeleteAllItems.

    using (SPSite sPSite = new SPSite("http://localhost"))

    {

        using (SPWeb sPWeb = sPSite.RootWeb)

        {

            SPList sPList;

            Stopwatch stopWatch = new Stopwatch();

 

            if (sPWeb.Lists.TryGet(STR_Annonces, out sPList))

            {

                Console.WriteLine("List : {0} Delete via Foreach\r\n\tBefore \tNB Items : {1}", STR_Annonces, sPList.ItemCount);

                stopWatch.Start();

                List<int> listId = new List<int>();

 

                foreach (SPListItem item in sPList.Items)

                    listId.Add(item.ID);

                foreach (int itemId in listId)

                    sPList.Items.DeleteItemById(itemId);

 

                sPList.Update();

                stopWatch.Stop();

                Console.WriteLine("\tAfter \tNB Items : {1}\tElapsed : {2} Msec",

                    STR_Annonces,

                    sPList.ItemCount,

                    stopWatch.ElapsedMilliseconds);

                stopWatch.Reset();

            }

 

            #region Rajout d'Elements à la liste STR_Annonces

 

            #endregion

 

            if (sPWeb.Lists.TryGet(STR_Annonces, out sPList))

            {

                Console.WriteLine("List : {0} Delete via Extension Method\r\n\tBefore \tNB Items : {1}", STR_Annonces, sPList.ItemCount);

                stopWatch.Start();

                sPList.DeleteAllItems(true, null);

                stopWatch.Stop();

                Console.WriteLine("\tAfter \tNB Items : {1}\tElapsed : {2} Msec",

                    STR_Annonces,

                    sPList.ItemCount,

                    stopWatch.ElapsedMilliseconds);

                stopWatch.Reset();

            }

        }

    }

En terme de performance, c'est assez impressionnant !

image

Voilà la méthode qui permet de réaliser ce petit tour de magie.

L'idée est d'utiliser ProcessBatchData pour effectuer sur un ensemble d'éléments la même action (ici, un Delete) en une seule fois. l'avantage de la méthode ProcessBatchData est qu'elle est extrêmement rapide (notamment car elle nécessite moins de traffics avec le serveur SQL).

Cependant, cette méthode n'est pas forcément des plus intuitives à utiliser et j'ai trouver intéressant de l'encapsuler dans une extension de méthode. L'ensemble de la requête est basé sur du CAML et l'utilisation de mot clef (SetList, Set Var, etc...)

PS : Dans les exemples ci-dessus, je n'utilise pas le paramètre metadata, j'en expliquerais l'utilité par la suite.

    /// <summary>

    /// Delete all the items specified via the metadata dictionnary (ID, FileUrl), FileUrl has to be null for SPList

    /// If metadata is null, it will delete every items in the list

    /// Use SPWeb.ProcessBatchData to execute the delete command

    /// cf : http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.processbatchdata.aspx

    /// </summary>

    /// <param name="oList">The List</param>

    /// <param name="forceUpdate">Will force the list update</param>

    /// <param name="metadata">Dictionnary with Key = Id and Value = Fileurl (if needed)</param>

    public static string DeleteAllItems(this SPList oList, bool forceUpdate, Dictionary<string, string> metadata)

    {

        bool isDocumentLivrary = oList is SPDocumentLibrary;

 

        StringBuilder sbDelete = new StringBuilder(170 * oList.ItemCount);

        sbDelete.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Batch OnError='Return'>");

        StringBuilder cmd = new StringBuilder(200);

        //Get the ListGuid, format to receive the Item ID and set the CMD to delete.

        cmd.AppendFormat("<Method><SetList Scope=\"Request\">{0}</SetList><SetVar Name=\"ID\">{{0}}</SetVar><SetVar Name=\"Cmd\">Delete</SetVar>", oList.ID);

 

        //Cmd Delete needs FileRef when it's a DocumentLibrary http://www.sharepointblogs.com/smc750/archive/2008/04/03/spweb-processbatchdata-a-list-is-a-list-is-a-list.aspx

        if (isDocumentLivrary)

            cmd.Append("<SetVar Name=\"owsfileref\">{1}</SetVar>");

        cmd.Append("</Method>");

 

        //Only items defined in the dictionnary will be deleted

        if (metadata != null)

            foreach (KeyValuePair<string, string> pair in metadata)

            {

                string itemId = pair.Key;

                if (isDocumentLivrary)

                    sbDelete.Append(string.Format(cmd.ToString(), itemId, pair.Value));

                else

                    sbDelete.Append(string.Format(cmd.ToString(), itemId));

            }

        else

            foreach (SPListItem item in oList.Items)

            {

                string itemId = item.ID.ToString();

                if (isDocumentLivrary)

                    sbDelete.Append(string.Format(cmd.ToString(), itemId, item.File.Url));

                else

                    sbDelete.Append(string.Format(cmd.ToString(), itemId));

            }

 

        sbDelete.Append("</Batch>");

 

        SPWeb oListParentWeb = oList.ParentWeb;

        string batchResult = oListParentWeb.ProcessBatchData(sbDelete.ToString());

 

        if (forceUpdate)

            oList.Update();

 

        //Dispose !!! http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx

        oListParentWeb.Dispose();

 

        return ResultFromBatchCommand(batchResult);

    }

 

    private static string ResultFromBatchCommand(string batchResult)

    {

        string result = String.Empty;

 

        XmlDocument xmlDoc = new XmlDocument();

        xmlDoc.LoadXml(batchResult);

        XmlNodeList xmlErrNodes = xmlDoc.SelectNodes("/Results/Result/ErrorText");

        int nbErrors = xmlErrNodes.Count;

 

        if (nbErrors > 0)

            result = xmlErrNodes[0].InnerText;

 

        return result;

    }

Vous l'aurez compris, c'est une méthode très intéressante dès que vous aurez une action à effectuer sur un ensemble d'éléments (ce qui arrive souvent avec SharePoint).

Pour revenir sur l'utilisation du paramètre metadata, j'avais envie de pouvoir supprimer simplement un ensemble d'éléments dans une liste. Pour ce faire, j'avais besoin de préciser l'ID et éventuellement l'URL vers le fichier (si c'est une DocumentLibrary) du coup, j'ai décider d'utiliser un dictionnary : La clef serait l'ID et éventuellement en valeur je stocke l'URL du fichier.

En pratique, si je souhaite supprimer tout les éléments de la liste Annonces qui ont pour couleur "Red", il me suffit de faire la requête CAML adéquate et de passer les informations nécessaires à ma méthode

    if (sPWeb.Lists.TryGet(STR_Annonces, out sPList))

    {

        SPQuery query = new SPQuery();

        query.Query = "<Where><Eq><FieldRef Name='Color' /><Value Type='Text'>Red</Value></Eq></Where><OrderBy />";

 

        SPListItemCollection itemCollection = sPList.GetItems(query);

 

        Dictionary<string, string> metadata = new Dictionary<string, string>();

        foreach (SPListItem item in itemCollection)

            metadata.Add(item.ID.ToString(), null);

 

        Console.WriteLine("List : {0} Delete via Extension Method\r\n\tBefore \tNB Items : {1}", STR_Annonces, sPList.ItemCount);

        sPList.DeleteAllItems(true, metadata);

        Console.WriteLine("\tAfter \tNB Items : {1}", STR_Annonces, sPList.ItemCount);

    }

Il me reste encore quelques détails à re-travailler sur cette méthode (notamment gérer les erreurs) , n'hésitez pas à me faire part de vos remarques/optimisations.

<Philippe/>

Publié mardi 20 mai 2008 08:00 par phil
Classé sous , , ,
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

# re: SharePoint 2007 : Extension Method (DeleteAllItems) @ mardi 20 mai 2008 10:08

Allez, juste pour faire mon gros relou, et parce que c'est facile de pinailler quand on tient pas son blog super à jour... On dit pas "extension de méthode" mais "méthode d'extension"...

Allez, tiens et tant qu'à faire mon gros relou, quand on parle de réflection en français, c'est un peu par abus de langage, le terme adapté est "introspection" (ouais ouais je sais, moi aussi je dis "réflection", mais j'avais prévenu, je suis relou).

Allez, bravo quand même pour ton blog ;)

simon ferquel

# re: SharePoint 2007 : Extension Method (DeleteAllItems) @ mardi 20 mai 2008 10:13

lol, quand je parlais de remarques, je pensais plus à des remarques techniques :)

ceci dit, ton point est valide. je fais les modifs.

Merci Simon'

phil

About phil

Leader Technique SharePoint chez Winwise, je m'occupe de missions d'expertise autour de WSS 3.0 et MOSS 2007, tout en me tenant au courant de ce qui se fait autour de Asp.net, Silverlight et des technologies Web by Microsoft en général.

Les 10 derniers blogs postés

- un Pacman en Silverlight 2b2 par Pierrick's Blog le il y a 5 heures et 14 minutes

- Une table -> deux entity types sans colonne discriminante en base, gestion des relations par Matthieu MEZIL le il y a 13 heures et 13 minutes

- ssdl view et TPT par Matthieu MEZIL le 07-05-2008, 02:04

- L'injection SQL n'est PAS un problème QUE pour les développeurs web ! par CoqBlog le 07-05-2008, 01:08

- Un outil pour réaliser des animations WPF basées sur des équations de Bézier par Perspective le 07-04-2008, 21:45

- Sandcastle et CodePlex : le verdict par CoqBlog le 07-04-2008, 20:53

- ssdl view et TPH par Matthieu MEZIL le 07-04-2008, 19:12

- Webcasts sur le Parallel Framework disponibles par Matthieu MEZIL le 07-04-2008, 17:26

- [Silverlight] - Comprendre et Débuter avec Silverlight par Danuz le 07-04-2008, 12:41

- SharePoint : Nouvel article sur l'exportation et Importation de sites SharePoint par Blog Technique de Romelard Fabrice le 07-04-2008, 01:00