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

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 12 heures et 48 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 14 heures et 2 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le 07-03-2009, 09:56

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le 07-03-2009, 09:00

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le 07-03-2009, 08:45

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

- EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18