SharePoint 2007 : Extension Method (AddItems)

Lors des précédent billets sur les extensions de méthode, je vous ai parlé d'un manière plus intuitive de récupèrer une SPList (mais potentiellement SPWeb, SPUser, etc...), je vous ai aussi montrer comment gagner énormément de temps lors de la suppression d'élements dans vos liste et finalement, pour boucler la boucle, je vais vous montrer aujourd'hui une méthode qui vous permet d'ajouter simplement des éléments dans une liste en évitant la méthode classique qui peut sembler rébarbative:

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

{

    using (SPWeb web = site.RootWeb)

    {

        SPList listAnnonces;

        Stopwatch stopWatch = new Stopwatch();

 

        //So easy to get a SPList like that.

        if (web.Lists.TryGet(STR_Annonces, out listAnnonces))

        {

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

            Random rnd = new Random();

 

            SPListItemCollection listAnnoncesItems = listAnnonces.Items;

            //Generate a paragraph of Lipsum from http://code.google.com/p/nlipsum/

            string bodyContent = LipsumGenerator.Generate(1);

            stopWatch.Start();

 

            for (int i = 0; i < 100; i++)

            {

                SPListItem item = listAnnoncesItems.Add();

                item["Title"] = rnd.Next();

                item["Body"] = bodyContent;

                item["Expires"] = DateTime.Now;

                item.Update();

            }

            listAnnonces.Update();

 

            stopWatch.Stop();

 

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

                STR_Annonces,

                listAnnonces.ItemCount,

                stopWatch.ElapsedMilliseconds);

 

            stopWatch.Reset();

...

Et encore ici, je triche un peu en utilisant ma méthode d'extension qui me permet de simplifier l'accès à la liste.

Maintenant si je compare en utilisant l'extension de méthode AddItems sur une SPList:

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

{

    using (SPWeb web = site.RootWeb)

    {

        SPList listAnnonces;

        Stopwatch stopWatch = new Stopwatch();

 

        //So easy to get a SPList like that.

        if (web.Lists.TryGet(STR_Annonces, out listAnnonces))

        {

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

 

            //Create the Data you will insert in each Items

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

            metadata.Add("Title", null);

            //Generate a paragraph of Lipsum from http://code.google.com/p/nlipsum/

            metadata.Add("Body", LipsumGenerator.Generate(1));

            string validDateTimeFormat = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now);

            // We need to insert a valid dateTime with a specific format : 2008-06-01T14:02:08Z

            metadata.Add("Expires", validDateTimeFormat);

 

            stopWatch.Start();

            listAnnonces.AddItems(100, metadata, true);

            stopWatch.Stop();

 

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

                listAnnonces.ItemCount,

                stopWatch.ElapsedMilliseconds);

        }

 

         //Another Example with a different format (URL)

        if (web.Lists.TryGet(STR_Liens, out listAnnonces))

        {

            Console.WriteLine("List : {0}, Number of Items  : {1}", STR_Liens, listAnnonces.ItemCount);

 

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

            metadata.Add("URL", http://localhost, Home);

            metadata.Add("Comments", LipsumGenerator.Generate(1));

 

            listAnnonces.AddItems(10, metadata, true);

 

            Console.WriteLine("List : {0}, Number of Items  : {1}", STR_Liens, listAnnonces.ItemCount);

        }

    }

}

Au final, ces appels nous donne en sortie la création de 100 éléments chacun, voyons la différence en terme de rapidité.

diff_classic_and_extension

Encore une fois, c'est l'utilisation de ProcessBatchData qui nous permet d'avoir cette différence de performance. L'utilisation en elle-même n'est pas des plus aisée, d'où l'intérêt de l'encapsuler dans cette extension de méthode :

/// <summary>

/// Adds Item to the selected List, will use the metadata to insert data into Columns

/// Will throw an SPException if an error occurs or If Metadata is null

/// </summary>

/// <param name="list">The list.</param>

/// <param name="nbItems">The Number of items to create</param>

/// <param name="metadata">The metadata used to insert data into Items.</param>

public static void AddItems(this SPList list, int nbItems, Dictionary<string, string> metadata, bool forceUpdate)

{

    if (metadata == null)

        throw new SPException("AddItems : Metadata can't be null");

 

    // Adding 0 items...

    if (nbItems == 0)

        return;

 

    StringBuilder sbAdd = new StringBuilder(100 * nbItems);

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

    Guid listGuid = list.ID;

    for (int i = 0; i < nbItems; i++)

    {

        sbAdd.AppendFormat("<Method ID=\"{0},Save\"><SetList>{1}</SetList><SetVar Name=\"ID\">New</SetVar><SetVar Name=\"Cmd\">Save</SetVar>", i, listGuid);

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

        {

            string value = pair.Value;

            //Just in case, i wan't a field with pseudo random content, should propably improve this.

            if (value == null)

                value = rnd.Next().ToString();

            sbAdd.AppendFormat("<SetVar Name=\"urn:schemas-microsoft-com:office:office#{0}\">{1}</SetVar>", pair.Key, value);

        }

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

    }

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

 

    SPWeb oListParentWeb = list.ParentWeb;

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

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

    oListParentWeb.Dispose();

 

    if (forceUpdate)

        list.Update();

 

    string errorMessage = ResultFromBatchCommand(batchResult);

    if (errorMessage != String.Empty)

        throw new SPException(errorMessage);

}

Si vous avez d'autre idées de méthodes ou d'optimisations, n'hésitez à pas à laisser un commentaire.

<Philippe/>

Publié lundi 2 juin 2008 10:30 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

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

- Entity Framework : providers Oracle, MySQL et PostgreSQL par Matthieu MEZIL le il y a 6 heures et 20 minutes

- [WPF] Nouvel article sur c2i.fr par Richard Clark le il y a 22 heures et 57 minutes

- F# nouvelle CTP 1.9.6.2 (update) par Pierrick's Blog le 09-06-2008, 13:27

- La suite ...Proposition de collaboration rédactionnelle entre les communautés de développeurs et Microsoft France par LucasR le 09-05-2008, 17:45

- [Fun] Votre simulateur de vol avec Microsoft ESP par Julien Chable le 09-05-2008, 12:02

- [Best Practices] Customisation du My Site : Comment le modifier en amont et en aval par The Mit's Blog le 09-05-2008, 10:47

- Patrick Tisseghem s'en est allé ... par The Mit's Blog le 09-05-2008, 10:04

- MS AutoCollage par alex# le 09-05-2008, 09:18

- Un grand SharePointeur nous a quitte : Patrick Tisseghem manquera à la communauté ! par RedoBlog - The .NET Gentleman !!! le 09-05-2008, 08:52

- [WPF] Comment charger dynamiquement un fichier XAML qui définit des eventhandler ? par Thomas Lebrun le 09-04-2008, 10:56