Friday, November 4, 2011

SharePoint Batch Add, Update and Delete

Recently we needed to use SharePoint Batch commands to create, update and delete items in lists. I created a simple handler which allows to easily build such queries. And you're welcome to use it.

How to use it:
Assuming we have following DTO/Model object:

public class TestListItem : IContainsId
{
public int Id { get; set; }
public string SomeText { get; set; }
public int SomeCount { get; set; }
}
And we have a list with string column "CustomSomeText" and Number column "CustomSomeCount". We could use following code to batch add/update/delete this items to list:

var items = new List<TestListItem>
{
new TestListItem{Id = 1, SomeCount = 1, SomeText ="One"},
new TestListItem{Id = 3, SomeCount = 9, SomeText ="Three"},
new TestListItem{Id = 5, SomeCount = 25, SomeText ="Twenty Five"}
};
var builder = new BatchBuilder<TestListItem>();
var fields = new[] { "CustomSomeText", "CustomSomeCount" };
var selectors = new Func<TestListItem, string>[] { x => x.SomeText, x => x.SomeCount.ToString() };
using (var site = new SPSite("http://sitecollection"))
{
var web = site.RootWeb;
var list = web.Lists["batch"];
//var command = builder.GetAddCommand(items, fields, selectors, list.ID);
//var command = builder.GetUpdateCommand(items, fields, selectors, list.ID);
var command = builder.GetDeleteCommand(items, list.ID);
string result = web.ProcessBatchData(command);
Console.WriteLine(result);
}
I think it's pretty straightforward.



IContainsId.cs

public interface IContainsId
{
    int Id { get; }
}

BatchBuilder.cs

public class BatchBuilder<T> where T : IContainsId
{
    #region Constants
    public const string BATCH_START =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ows:Batch OnError=\"Return\">";
    public const string BATCH_END = "</ows:Batch>";
    public const string UPDATE_COMMAND_FORMAT = "<Method ID=\"{0}\">" +
                                "<SetList>{1}</SetList>" +
                                "<SetVar Name=\"Cmd\">Save</SetVar>" +
                                "<SetVar Name=\"ID\">{2}</SetVar>{3}" +
                                "</Method>";
    public const string ADD_COMMAND_FORMAT = "<Method ID=\"{0}\">" +
                                "<SetList>{1}</SetList>" +
                                "<SetVar Name=\"Cmd\">Save</SetVar>" +
                                "<SetVar Name=\"ID\">New</SetVar>{2}" +
                                "</Method>";
    public const string DELETE_COMMAND_FORMAT = "<Method ID=\"{0}\">" +
                                "<SetList>{1}</SetList>" +
                                "<SetVar Name=\"Cmd\">Delete</SetVar>" +
                                "<SetVar Name=\"ID\">{0}</SetVar>" +
                                "</Method>";
    #endregion
    #region Public Methods
    public string GetUpdateCommand(IEnumerable<T> itemsToUpdate, string[] fieldNames, Func<T, string>[] selectors, Guid listId)
    {
        if (fieldNames.Length == 0 || selectors.Length == 0 || fieldNames.Length != selectors.Length)
        {
            throw new ArgumentException();
        }
        var batchBuilder = new StringBuilder(BATCH_START);
        foreach (var itemToUpdate in itemsToUpdate)
        {
            var id = itemToUpdate.Id;
            var fieldsBuilder =
                fieldNames.Select(
                    (x, i) => string.Format("<SetVar Name=\"urn:schemas-microsoft-com:office:office#{0}\">{1}</SetVar>", x, selectors[i].Invoke(itemToUpdate)))
                    .Aggregate(new StringBuilder(), (c, n) => c.Append(n));
            batchBuilder.AppendFormat(UPDATE_COMMAND_FORMAT, id, listId, id, fieldsBuilder);
        }
        batchBuilder.Append(BATCH_END);
        return batchBuilder.ToString();
    }
    public string GetAddCommand(IEnumerable<T> itemsToAdd, string[] fieldNames, Func<T, string>[] selectors, Guid listId)
    {
        if (fieldNames.Length == 0 || selectors.Length == 0 || fieldNames.Length != selectors.Length)
        {
            throw new ArgumentException();
        }
        var batchBuilder = new StringBuilder(BATCH_START);
        var methodId = 1;
        foreach (var itemToAdd in itemsToAdd)
        {
            var fieldsBuilder =
                fieldNames.Select(
                    (x, i) => string.Format("<SetVar Name=\"urn:schemas-microsoft-com:office:office#{0}\">{1}</SetVar>", x, selectors[i].Invoke(itemToAdd)))
                    .Aggregate(new StringBuilder(), (c, n) => c.Append(n));
            batchBuilder.AppendFormat(ADD_COMMAND_FORMAT, methodId, listId, fieldsBuilder);
            ++methodId;
        }
        batchBuilder.Append(BATCH_END);
        return batchBuilder.ToString();
    }
    public string GetDeleteCommand(IEnumerable<T> itemsToDelete, Guid listId)
    {
        var batchBuilder = new StringBuilder(BATCH_START);
        foreach (var itemToDelete in itemsToDelete)
        {
            batchBuilder.AppendFormat(DELETE_COMMAND_FORMAT, itemToDelete.Id, listId);
        }
        batchBuilder.Append(BATCH_END);
        return batchBuilder.ToString();
    }
    #endregion
}


No comments:

Post a Comment