Partager via


Gestion de dossiers et de listes volumineux

Dernière modification : vendredi 10 juin 2011

S’applique à : SharePoint Foundation 2010

Dans cet article
Limitation des requêtes de liste volumineuse
Utilisation des dossiers et des listes
Suppression de plusieurs versions d’un élément de liste

Lorsque la taille des dossiers et des listes augmente, vous devez concevoir un code personnalisé qui leur soit adapté afin d’optimiser les performances. Sinon, vos applications s’exécuteront lentement et provoqueront des délais de service ou de chargement de page. Les deux principaux problèmes lors de la manipulation de listes et de dossiers volumineux sont les suivants :

  • la limitation des requêtes, qui peut entraîner une modification inattendue et imprévisible de votre code au fil du temps, tandis que votre site évolue et que vos requêtes commencent à retourner des éléments qui dépassent le seuil de requêtes ;

  • la récupération efficace d’éléments provenant de listes et de dossiers volumineux.

Pour résoudre ces deux problèmes, vous devez comprendre de quelle façon le modèle objet interagit avec les listes et les dossiers.

Limitation des requêtes de liste volumineuse

Microsoft SharePoint Foundation 2010 et Microsoft SharePoint Server 2010 appliquent un seuil de requêtes par défaut de 5 000 éléments. Tout code reposant sur les jeux de résultats de requête qui excèdent cette valeur maximale ne s’exécuteront pas comme prévu. Les requêtes de liste composées de plus de 5 000 éléments incluant des champs non indexés dans leurs conditions de requête échoueront également, car ces requêtes doivent parcourir toutes les lignes d’une liste. Suivez les étapes ci-après pour afficher et accroître cette limite ou pour permettre au modèle objet de remplacer la limite.

Pour afficher et accroître le seuil ou permettre au modèle objet de remplacer le seuil

  1. Sur le site Administration centrale, sous Gestion des applications, cliquez sur Gérer les applications Web.

  2. Cliquez sur Paramètres généraux, puis sur Limitation de ressource.

  3. Affichez et modifiez le seuil, ou autorisez le modèle objet à remplacer la limite.

Utilisation des dossiers et des listes

Les recommandations relatives à la prise en compte des problèmes de performance lors de l’utilisation de dossiers et de listes volumineux s’appuient sur les résultats des tests dont fait état Steve Peschka dans son livre blanc, Utilisation de listes volumineuses dans Office SharePoint Server 2007 (éventuellement en anglais). Ces recommandations s’appliquent aussi à Microsoft SharePoint Server 2010. Pour plus d’instructions sur l’utilisation de SPQuery et de la classe PortalSiteMapProvider, qui s’applique spécifiquement à SharePoint Server 2010, voir Écriture d’un code efficace dans SharePoint Server.

Lorsque vous utilisez les dossiers et les listes 

  • N’utilisez pas SPList.Items.

    SPList.Items sélectionne tous les éléments de tous les sous-dossiers, y compris tous les champs de la liste. Utilisez les alternatives suivantes pour chaque cas d’utilisation.

    • Ajout d’un élément

      Au lieu d’appeler SPList.Items.Add, utilisez SPList.AddItem.

    • Récupération de tous les éléments d’une liste

      Au lieu d’utiliser SPList.Items, choisissez SPList.GetItems(SPQuery query) . Appliquez les filtres, si nécessaire, et spécifiez uniquement les champs dont vous avez besoin pour rendre la requête plus efficace. Si la liste contient plus de 2 000 éléments, parcourez la liste par incréments de 2 000 éléments au plus. L’exemple de code suivant montre comment paginer une liste volumineuse.

      Bonne pratique de programmation

      Récupération d’éléments avec SPList.GetItems

      SPQuery query = new SPQuery();
      SPListItemCollection spListItems ; 
      string lastItemIdOnPage = null; // Page position.
      int itemCount = 2000
       
      while (itemCount == 2000)
      {
          // Include only the fields you will use.
          query.ViewFields = "<FieldRef Name=\"ID\"/><FieldRef Name=\"ContentTypeId\"/>";   
          query.RowLimit = 2000; // Only select the top 2000.
          // Include items in a subfolder (if necessary).
          query.ViewAttributes = "Scope=\"Recursive\"";
          StringBuilder sb = new StringBuilder();
          // To make the query order by ID and stop scanning the table, specify the OrderBy override attribute.
          sb.Append("<OrderBy Override=\"TRUE\"><FieldRef Name=\"ID\"/></OrderBy>");
          //.. Append more text as necessary ..
          query.Query = sb.ToString();
          // Get 2,000 more items.
       
          SPListItemCollectionPosition pos = new SPListItemCollectionPosition(lastItemIdOnPage);
          query.ListItemCollectionPosition = pos; //Page info.
          spListItems = spList.GetItems(query);
          lastItemIdOnPage = spListItems.ListItemCollectionPosition.PagingInfo;
          // Code to enumerate the spListItems.
          // If itemCount <2000, finish the enumeration.
          itemCount = spListItems.Count;
      
      }
      
      Dim query As New SPQuery()
      Dim spListItems As SPListItemCollection
      Dim lastItemIdOnPage As String = Nothing ' Page position.
      Dim itemCount As Integer = 2000
      
      Do While itemCount = 2000
          ' Include only the fields you will use.
          query.ViewFields = "<FieldRef Name=""ID""/><FieldRef Name=""ContentTypeId""/>"
          query.RowLimit = 2000 ' Only select the top 2000.
          ' Include items in a subfolder (if necessary).
          query.ViewAttributes = "Scope=""Recursive"""
          Dim sb As New StringBuilder()
          ' To make the query order by ID and stop scanning the table, specify the OrderBy override attribute.
          sb.Append("<OrderBy Override=""TRUE""><FieldRef Name=""ID""/></OrderBy>")
          '.. Append more text as necessary ..
          query.Query = sb.ToString()
          ' Get 2,000 more items.
      
          Dim pos As New SPListItemCollectionPosition(lastItemIdOnPage)
          query.ListItemCollectionPosition = pos 'Page info.
          spListItems = spList.GetItems(query)
          lastItemIdOnPage = spListItems.ListItemCollectionPosition.PagingInfo
          ' Code to enumerate the spListItems.
          ' If itemCount <2000, finish the enumeration.
          itemCount = spListItems.Count
      Loop
      

      L’exemple suivant montre comment énumérer et paginer une liste volumineuse.

      SPWeb oWebsite = SPContext.Current.Web;
      SPList oList = oWebsite.Lists["Announcements"];
      
      SPQuery oQuery = new SPQuery();
      oQuery.RowLimit = 10;
      int intIndex = 1;
      
      do
      {
          Response.Write("<BR>Page: " + intIndex + "<BR>");
          SPListItemCollection collListItems = oList.GetItems(oQuery);
      
          foreach (SPListItem oListItem in collListItems)
          {
              Response.Write(SPEncode.HtmlEncode(oListItem["Title"].ToString()) +"<BR>");
          }
      
          oQuery.ListItemCollectionPosition = collListItems.ListItemCollectionPosition;
          intIndex++;
      } while (oQuery.ListItemCollectionPosition != null);
      
       Dim oWebsite As SPWeb = SPContext.Current.Web
      Dim oList As SPList = oWebsite.Lists("Announcements")
      
      Dim oQuery As New SPQuery()
      oQuery.RowLimit = 10
      Dim intIndex As Integer = 1
      
      Do
          Response.Write("<BR>Page: " & intIndex & "<BR>")
          Dim collListItems As SPListItemCollection = oList.GetItems(oQuery)
      
          For Each oListItem As SPListItem In collListItems
              Response.Write(SPEncode.HtmlEncode(oListItem("Title").ToString()) & "<BR>")
          Next oListItem
      
          oQuery.ListItemCollectionPosition = collListItems.ListItemCollectionPosition
          intIndex += 1
      Loop While oQuery.ListItemCollectionPosition IsNot Nothing
      
    • Obtention d’éléments par identificateur

      Au lieu d’utiliser SPList.Items.GetItemById, choisissez SPList.GetItemById(int id, string field1, params string[] fields). Spécifiez l’identificateur d’élément et le champ de votre choix.

  • N’énumérez pas de collections SPList.Items ou de collections SPFolder.Files complètes.

    La colonne de gauche du tableau 1 dresse la liste des méthodes et des propriétés qui, si elles sont utilisées, énumèrent la totalité de la collection SPList.Items et entraînent de médiocres performances et une limitation pour les listes volumineuses. Utilisez à la place les solutions aux meilleures performances proposées dans la colonne de droite.

    Tableau 1. Solutions de remplacement de l’énumération de SPList.Items

    Méthodes et propriétés aux performances médiocres

    Solutions de remplacement aux performances meilleures

    SPList.Items.Count

    SPList.ItemCount

    SPList.Items.XmlDataSchema

    Créez un objet SPQuery pour n’extraire que les éléments de votre choix.

    SPList.Items.NumberOfFields

    Créez un objet SPQuery (spécifiant les ViewFields) pour n’extraire que les éléments de votre choix.

    SPList.Items[System.Guid]

    SPList.GetItemByUniqueId(System.Guid)

    SPList.Items[System.Int32]

    SPList.GetItemById(System.Int32)

    SPList.Items.GetItemById(System.Int32)

    SPList.GetItemById(System.Int32)

    SPList.Items.ReorderItems(System.Boolean[],System.Int32[],System.Int32)

    Exécutez une requête paginée à l’aide de SPQuery et réordonnez les éléments au sein de chaque page.

    SPList.Items.ListItemCollectionPosition

    ContentIterator.ProcessListItems(SPList, ContentIterator.ItemProcessor, ContentIterator.ItemProcessorErrorCallout) (Microsoft SharePoint Server 2010 uniquement)

    SPList.Items.ListItemCollectionPosition

    ContentIterator.ProcessListItems(SPList, ContentIterator.ItemProcessor, ContentIterator.ItemProcessorErrorCallout) (SharePoint Server 2010 uniquement)

    Notes

    L’utilisation de la propriété SPList.ItemCount est la solution recommandée pour extraire le nombre d’éléments d’une liste. Cependant, conséquence de son réglage à des fins de performance, la propriété peut occasionnellement retourner des résultats inattendus.Par exemple, si vous voulez le nombre exact d’éléments, vous devez utiliser GetItems(SPQuery query) aux performances plus médiocres, comme illustré dans l’exemple de code précédent.

  • Chaque fois que possible, obtenez une référence à une liste en utilisant le GUID de liste ou l’URL comme clé.

    Vous pouvez extraire un objet SPList de la propriété SPWeb.Lists en utilisant le GUID de liste ou le nom complet comme indexeur. L’utilisation de SPWeb.Lists[GUID] et de SPWeb.GetList(strURL) est toujours préférable à celle de SPWeb.Lists[strDisplayName]. L’utilisation du GUID est préférable, car il est unique, permanent, et ne nécessite qu’une seule recherche de base de données. L’indexeur de noms complets extrait les noms de toutes les listes du site, puis procède à une comparaison de chaîne. Si vous avez une URL de liste à la place d’un GUID, vous pouvez utiliser la méthode GetList de SPWeb pour rechercher le GUID de liste dans la base de données du contenu avant d’extraire la liste.

  • N’énumérez pas les collections SPFolder.Files complètes.

    La colonne de gauche du tableau 2 dresse la liste des méthodes et des propriétés qui gonflent la collection SPFolder.Files et entraînent de médiocres performances et une limitation pour les listes volumineuses. Utilisez à la place les solutions aux meilleures performances proposées dans la colonne de droite.

    Tableau 2. Solutions de remplacement de SPFolders.Files

    Méthodes et propriétés aux performances médiocres

    Solutions de remplacement aux performances meilleures

    SPFolder.Files.Count

    SPFolder.ItemCount

    SPFolder.Files.GetEnumerator()

    ContentIterator.ProcessFilesInFolder(SPFolder, System.Boolean, ContentIterator.FileProcessor, ContentIterator.FileProcessorErrorCallout) (SharePoint Server 2010 uniquement)

    SPFolder.Files[System.String]

    ContentIterator.GetFileInFolder(SPFolder, System.String)Le cas échéant, SPFolder.ParentWeb.GetFile(SPUrlUtility.CombineUrl(SPFolder.Url, System.String) (SharePoint Server 2010 uniquement)

    SPFolder.Files[System.Int32]

    Ne pas utiliser. Passez à ContentIterator.ProcessFilesInFolder et comptez les éléments pendant l’itération. (SharePoint Server 2010 uniquement)

Suppression de plusieurs versions d’un élément de liste

Lorsque vous supprimez plusieurs versions d’un élément de liste, utilisez la méthode DeleteByID() ; ne recourez pas à la méthode Delete(). Vous rencontrerez des problèmes de performances si vous supprimez chaque objet SPListItemVersion d’un objet SPListItemVersionCollection. La procédure recommandée consiste à créer un tableau qui contient les propriétés d’ID de chaque version, puis à supprimer chaque version à l’aide de la méthode SPFileVersionCollection.DeleteByID. Les exemples de code suivants illustrent l’approche non recommandée et l’approche recommandée pour supprimer toutes les versions du premier élément d’une liste personnalisée.

Mauvaise pratique de programmation

Suppression de chaque objet SPListItemVersion

SPSite site = new SPSite("site url");
SPWeb web = site.OpenWeb();
SPList list = web.Lists["custom list name"];
SPListItem item = list.GetItemById(1); 
SPListItemVersionCollection vCollection = item.Versions;
ArrayList idList = new ArrayList();
foreach(SPListItemVersion ver in vCollection)
{
  idList.Add(ver.VersionId);
}
foreach(int verID in idList)
{
  SPListItemVersion version = vCollection.GetVersionFromID(verID); 
try
{
  version.Delete();
}
catch (Exception ex)
{
  MessageBox.Show(ex.Message);  
}
}

Bonne pratique de programmation

Suppression de chaque version d’un élément de liste à l’aide de la méthode SPFileVersionCollection.DeleteByID

SPSite site = new SPSite("site url");
SPWeb web = site.OpenWeb();
SPList list = web.Lists["custom list name"];
SPListItem item = list.GetItemById(1);
SPFile file = web.GetFile(item.Url);
SPFileVersionCollection collection = file.Versions;
ArrayList idList = new ArrayList();
foreach (SPFileVersion ver in collection)
{
  idList.Add(ver.ID);
}
foreach (int verID in idList)
{
try
{
  collection.DeleteByID(verID);
}
catch (Exception ex)
{
  MessageBox.Show(ex.Message);  
}
}

Si vous supprimez des versions d’éléments se trouvant dans une bibliothèque de documents, vous pouvez utiliser une approche similaire en récupérant la méthode SPListItem.File.Versions, comme illustré dans l’exemple de code suivant.

Bonne pratique de programmation

Suppression de chaque version d’un élément de liste dans une bibliothèque de documents à l’aide de la méthode SPFileVersionCollection.DeleteByID

SPSite site = new SPSite("site url");
SPWeb web = site.OpenWeb();
SPList list = web.Lists["custom list name"];

SPFile file = list.RootFolder.Files[0];
SPFileVersionCollection collection = file.Versions;
ArrayList idList = new ArrayList();
foreach (SPFileVersion ver in collection)
{
  idList.Add(ver.ID);
}
foreach (int verID in idList)
{
try
{
  collection.DeleteByID(verID);
}
catch (Exception ex)
{
  MessageBox.Show(ex.Message);  
}
}