Simple SharePoint List Repository

  2014-03-13


The last couple of months I’ve been diving deep into the SharePoint development. The experience so far has not been the most pleasant, but I’m not gonna whine, because the platform itself is a really good one in my opinion, but it’s just that I don’t like working with such massive CMS systems.

Anyhow, below is a simple class which I wrote to help with some simple data retrieval from a SharePoint list. We are doing our data access with CAML queries, and doing certain things with CAML queries is not that straight-forward, so here comes the wrapper for some things I needed to do.

namespace My.DataAccess.Utilities
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.SharePoint;

    /// <summary>
    /// Utility class providing simple methods to retrieve items from a SharePoint list.
    /// </summary>
    public class SimpleSharePointListRepository
    {
        /// <summary>
        /// Returns all items that match the provided query.
        /// </summary>
        /// <param name="webUrl">Absolute path to the web where the list is located,
        /// e.g. - "/news/international"</param>
        /// <param name="listName">Name of the list, e.g. - "Pages".</param>
        /// <param name="query">SPQuery instance.</param>
        /// <returns>IEnumerable of SPListItem.</returns>
        public static IEnumerable<SPListItem> GetAll(string webUrl, string listName, SPQuery query)
        {
            using (SPWeb web = SPContext.Current.Site.OpenWeb(webUrl))
            {
                query = query ?? new SPQuery { ViewFieldsOnly = false };
                var list = web.GetList(webUrl + "/" + listName);

                return list.GetItems(query).Cast<SPListItem>();
            }
        }

        /// <summary>
        /// Returns a number of randomly picked items that match the provided query.
        /// </summary>
        /// <param name="webUrl">Absolute path to the web where the list is located,
        /// e.g. - "/news/international"</param>
        /// <param name="listName">Name of the list, e.g. - "Pages".</param>
        /// <param name="query">SPQuery instance.</param>
        /// <param name="itemCount">Number of items to return. If there aren't enough items in the list,
        /// then this method will return all items from that list.</param>
        /// <returns>IEnumerable of SPListItem.</returns>
        public static IEnumerable<SPListItem> GetRandomSample(string webUrl, string listName, SPQuery query, int itemCount)
        {
            SPSite site = SPContext.Current.Site;

            using (SPWeb web = site.OpenWeb(webUrl))
            {
                SPList list = web.GetList(webUrl + "/" + listName);

                SPQuery countQuery = new SPQuery
                {
                    Query = query.Query,
                    RowLimit = int.MaxValue,
                    ViewFieldsOnly = true,
                    ViewFields = "<FieldRef Name='ID' />"
                };

                SPListItemCollection itemCollection = list.GetItems(countQuery);

                if (itemCount >= itemCollection.Count)
                {
                    return list.GetItems(query).Cast<SPListItem>().ToList();
                }

                var random = new Random();

                // Shuffle the items and get a random sample.
                var randomItems = itemCollection
                    .Cast<SPListItem>()
                    .OrderBy(i => random.Next())
                    .Take(itemCount);

                // Build the <In></In> query which will point to the selected random items.
                string inConditions = null;
                foreach (SPListItem randomItem in randomItems)
                {
                    inConditions += "<Value Type='Integer'>" + randomItem.ID + "</Value>";
                }

                var randomItemsQuery = new SPQuery
                {
                    RowLimit = (uint)itemCount,
                    ViewFieldsOnly = true,
                    Query = "<Where><In><FieldRef Name='ID'/><Values>" + inConditions + "</Values></In></Where>",
                    ViewFields = query.ViewFields
                };

                // Return the selected random items.
                return list.GetItems(randomItemsQuery)
                    .Cast<SPListItem>()
                    .ToList();
            }
        }

        /// <summary>
        /// Returns the number of items matching the provided query.
        /// </summary>
        /// <param name="webUrl">Absolute path to the web where the list is located,
        /// e.g. - "/news/international"</param>
        /// <param name="listName">Name of the list, e.g. - "Pages".</param>
        /// <param name="query">SPQuery instance.</param>
        /// <returns>Number of items.</returns>
        public static int GetCount(string webUrl, string listName, SPQuery query)
        {
            // CAML doesn't allow doing an equivalent of "select count(1)", therefore
            // we need to perform the actual query and retrieve data. To maximize performance
            // we only return a single field just to make sure we have some data.
            SPQuery countQuery = new SPQuery
            {
                Query = query.Query,
                RowLimit = int.MaxValue,
                ViewFieldsOnly = true,
                ViewFields = "<FieldRef Name='ID' />"
            };

            SPSite site = SPContext.Current.Site;

            using (SPWeb web = site.OpenWeb(webUrl))
            {
                return web
                    .GetList(webUrl + "/" + listName)
                    .GetItems(countQuery)
                    .Count;
            }
        }
    }
}

I hope this helps and as always, if you spot some problems, please drop a comment below. Cheer-e-o.

22bugs.co © 2017. All rights reserved.