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

Philippe Sentenac est Consultant SharePoint à Wygwam en région Parisienne. Il intervient essentiellement sur des missions liées à SharePoint (2007 et 2010 ) mais aussi autour du Web 2.0. Plus généralement, il s'intéresse à l'ASP.Net (MVC) , à Silverlight, et à tout ce qui est orienté Web en rapport avec les nouvelles technologies, qu'il pratique depuis 2006. Féru de développement, il est passionné par les problématiques de méthodologies et d'industrialisation du développement.

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01