La structure interne ainsi que le design d'AreaProg ont récemment été modifiés.
Suite à cela, le format de certains articles a été perturbé. Le problème est connu et en cours de résolution. Merci de votre compréhension.
using System;
using Microsoft.SharePoint;
using System.Diagnostics;
namespace AreaProgConsoleApplication {
class Program
{
static void Main()
{
using (SPSite site = new SPSite("http://pc-de-zick"))
{
using (SPWeb web = site.OpenWeb())
{
Stopwatch sw = new Stopwatch();
sw.Start();
SPList list = web.Lists["Test"];
for (int i = 0; i < 2000; ++i)
{
SPListItem it = list.Items.Add();
it["Title"] = "Item #" + i;
it.Update();
}
sw.Stop();
Console.WriteLine("2000 items inserted in : " + sw.Elapsed.TotalMilliseconds);
Console.Read();
}
}
}
}
}
Ce code n'a rien de bien compliqué. Nous récupérons tout d'abord une référence à la liste Test pour ensuite boucler 2000 fois sur la variable i et exécuter 2000 opérations Add sur les éléments de la liste. Nous modifions également le titre de ces éléments pour enfin sauvegarder les modifications. Nous utilisons également un StopWatch, qui n'est rien d'autre qu'un chronomètre, pour voir en combien de temps ce sont effectués les 2000 ajouts. Voiciles résultats obtenus par cette méthode :
Cette valeur étant en millisecondes, cela veut dire que les 2000 ajouts se sont effectués en presque 20 secondes. Remplacez maintenant le code précédent par :
using System;
using System.Text;
using Microsoft.SharePoint;
using System.Diagnostics;
namespace AreaProgConsoleApplication
{
class Program
{
static void Main()
{
using (SPSite site = new SPSite("http://pc-de-zick"))
{
using (SPWeb web = site.OpenWeb())
{
Stopwatch sw = new Stopwatch();
sw.Start();
SPList list = web.Lists["Test"];
StringBuilder expr = new StringBuilder();
string method = "<Method ID="{0}">" +
"<SetVar Name="Cmd">Save</SetVar>" +
"<SetList>{1}</SetList>" +
"<SetVar Name="ID">New</SetVar>" +
"<SetVar Name="urn:schemas-microsoft-com:office:office#Title">{2}</SetVar>" +
"</Method>";
for (int i = 0; i < 2000; ++i)
expr.AppendFormat(method, i, list.ID, "item #" + i);
string batch = string.Format("<?xml version="1.0" encoding="UTF-8"?><Batch OnError="Return">{0}</Batch>", expr);
web.ProcessBatchData(batch);
sw.Stop();
Console.WriteLine("2000 items inserted in : " + sw.Elapsed.TotalMilliseconds);
Console.Read();
}
}
}
}
}
Nous expliquerons cette architecture plus tard. Pour l'instant, regardons ce qu'elle donne en terme de performance :
Sur la capture d'écran ci-dessus, vous pouvez constatez que cette architecture permet d'exécuter les 2000 ajouts dans la liste en seulement 12 secondes, ce qui représente une diminution de la durée totale d'exécution de 8 secondes par rapport à la technique habituelle. Maintenant que l'efficacité de cette méthode a été démontrée, passons à l'explication de celle-ci.
Une requête batch n'est rien d'autre que du XML permettant d'indiquer clairement l'opération que nous voulons effectuer. Tout d'abord, nous devons déclarer le prologue de cette requête XML :
<?xml version="1.0" encoding="UTF-8"?>Soyez très prudent avec la syntaxe de cette ligne. Effectivement, récemment j'avais mis un espace avant le dernier "?" et cela ne voulait pas fonctionner, tout ça à cause de l'espace... 1h30 de ma vie partie en fumée ^^ Ensuite, nous devons utiliser les éléments permettant de contenir notre tâche :
<Batch OnError="Return"> </Batch>L'élément Batch va contenir de nombreux éléments Method qui permettront de dire quelles opérations devront être réalisées. Cet élément possède l'attribut OnError qui permet de définir le comportement de la requête dans le cas où celle-ci rencontrerait une erreur. Si cet attribut est définit sur Continue, la requête continuera de s'exécuter en ne tenant pas compte de l'erreur. Par contre, si cet attribut est définit sur Return, la requête n'ira pas plus loin. Nous avons ensuite les éléments Method. Un élément de ce type va nous permettre de définir une opération à effectuer sur une liste. Si nous revenons à notre exemple, nous avons ceci :
<Method ID="{0}">
</Method>
Un élément Method peut contenir un attribut ID. Celui-ci sera important en termes de débogage. En effet, si une erreur se produit lors de l'exécution de votre requête, la fonction renverra un message d'erreur en XML contenant l'ID de la méthode ayant générée l'erreur. Vous pourrez ainsi la rectifier facilement. Passons maintenant au corps de l'élément Method. Ce dernier contiendra des éléments permettant d'affecter des valeurs à des variables. Une fois ces valeurs affectées, l'opération pourra s'exécuter en se basant sur ces dernières. La première variable à définir permet d'indiquer quel type d'opération nous voulons exécuter. Ici, il s'agit d'ajouter des éléments dans une liste. Nous ferons donc cela en modifiant la valeur de la variable Cmd :
<SetVar Name="Cmd">Save</SetVar>La valeur de la variable Cmd doit être initialisée sur Save lorsque nous voulons ajouter ou mettre à jour des éléments dans une liste. La variable à définir ensuite est bien évidemment l'ID de la liste dans laquelle nous désirons travailler. Pour cela, nous devons utiliser l'élément SetList :
<SetList> </SetList>La valeur devant être passée à cet élément est simplement le GUID de la liste. Ensuite, nous devons toujours définir l'ID de l'élément que nous voulons ajouter/mettre à jour. Dans le cas d'un ajout, vous ne pouvez pas connaître l'ID que devra avoir l'élément, dans ce cas, vous devrez utiliser le mot clé New :
<SetVar Name="ID">New</SetVar>Nous utilisons donc à nouveau SetVar pour modifier la valeur de la variable ID. Enfin, la dernière étape consiste simplement à définir la valeur de nos champs. Pour cela, il suffit d'utiliser SetVar en faisant passer le nom du champ dans l'attribut Name. Notez cependant que le nom de ce champ devra être préfixé par le schéma de ce dernier, qui est généralement "urn:schemas-microsoft-com:office:office" :
<SetVar Name="urn:schemas-microsoft-com:office:office#Title">Valeur</SetVar>Nous assignons donc simplement la valeur Valeur au champ Title. Comme vous le constatez avec notre code, l'élément Batch va contenir 2000 éléments Method et cela ne posera pas de problème. Effectivement, un élément Batch peut contenir un nombre illimité de Method a exécuter. Une fois la requête construite, il ne nous reste plus qu'à la faire passer en argument de la fonction ProcessBatchData de l'élément SPWeb contenant la liste.
<Method ID="ID_de_methode"> <SetVar Name="Cmd">Save</SetVar> <SetList>ID-de-la-liste</SetList> <SetVar Name="ID">ID_item</SetVar> <SetVar Name="urn:schemas-microsoft-com:office:office#Title">Nouveau titre</SetVar> </Method>Nous utilisons à nouveau la valeur Save pour la variable Cmd indiquant ainsi que la méthode ajoutera ou mettra à jour un élément. Ici, étant donné que la variable ID est définie sur l'ID d'un élément existant, cela voudra dire que la méthode devra mettre cet élément à jour. Le reste de la méthode est identique à l'ajout. Il suffit de définir la nouvelle valeur pour le champ de l'élément et le tour est joué.
<Method ID="ID_de_methode"> <SetVar Name="Cmd">Delete</SetVar> <SetList>ID-de-la-liste</SetList> <SetVar Name="ID">ID_item</SetVar> </Method>Comme vous pouvez le constater, la syntaxe de la méthode est encore plus simple quand il s'agit de la suppression. La valeur de la variable Cmd devra cette fois être initialisée sur Delete pour indiquer qu'il s'agit d'une suppression d'élément. Bien entendu, nous devons toujours spécifier l'ID de la liste pour indiquer de quelle liste les éléments seront supprimés. Enfin, nous devons spécifier l'ID de l'élément à supprimer grâce à la variable ID. Ces trois éléments sont suffisant pour déclencher une suppression d'éléments.
<Method ID="ID"> <SetVar Name="Cmd">Save</SetVar> <SetList>ID-de-la-liste</SetList> <SetVar Name="urn:schemas-microsoft-com:office:office#ContentType">Folder</SetVar> <SetVar Name="owsfileref">/Lists/Test/Dossier 1</SetVar> <SetVar Name="ID">New</SetVar> </Method>Pour ce qui est de la variable ID et Cmd, cela ne change pas. Il faut également toujours définir l'ID de la liste sur laquelle on travaille grâce à SetList. La différence réside premièrement dans le fait que nous devons modifier le champ ContentType de l'élément sur Folder pour indiquer qu'il s'agit d'un dossier. Ensuite, si vous modifiez le champ Title de cet élément, cela ne changera pas son titre car, comme nous l'avons vu, c'est le nom du dossier et non son titre qui est affiché sous la colonne Titre de la liste. Nous allons donc modifier la valeur du champ owsfileref pour définir un nom de dossier correct. Sa forme est assez simple, il suffit de définir le chemin d'accès à la liste (/Lists/Test/) suivi du nom que nous voulons donner au dossier (Dossier 1). Pour ce qui est de créer un dossier dans un autre dossier, il suffit juste de le rajouter au chemin, par exemple : Lists/Test/Dossier 1/Dossier 2.
<Method ID="ID"> <SetVar Name="Cmd">Save</SetVar> <SetList>ID-de-la-liste</SetList> <SetVar Name="ID">Id_du_dossier</SetVar> <SetVar Name="owsfileref">/Lists/Test/Dossier 1</SetVar> <SetVar Name="owsnewfileref">/Lists/Test/Dossier 2</SetVar> <SetVar Name="urn:schemas-microsoft-com:office:office#ContentType">Folder</SetVar> </Method>Nous devons bien entendu utiliser l'ID du dossier pour le renommer mais nous devons également utiliser owsfileref pour le localiser. C'est le chemin d'accès relatif du dossier. Nous devons également définir owsnewfileref pour définir le nouveau nom du dossier. Enfin, nous précisons que l'opération est à effectuer sur un dossier grâce au champ ContentType que nous définissions sur Folder.
<Method ID="ID"> <SetVar Name="Cmd">Delete</SetVar> <SetList>ID-de-la-liste</SetList> <SetVar Name="ID">Id_du_dossier</SetVar> </Method>Cette requête se base donc uniquement sur l'ID du dossier pour effectuer la suppression.
Veuillez vous identifier ou vous inscrire pour donner une note à cet article.
Veuillez vous identifier ou vous inscrire pour réagir à cet article.
Mickaël (17/01/2011 - 15:33)
Je regrette cependant de ne pas avoir d'aide sur la meilleure façon de gérer le message d'erreur renvoyé par la méthode ProcessBatchData.
Une idée ?