Getting Changes from the Change Log

Applies to: SharePoint Foundation 2010

You can access the change log programmatically by calling the GetChanges method of an SPList, SPWeb, SPSite, or SPContentDatabase object. Calls made at each of these scopes are progressively more inclusive. In each case, the GetChanges method returns an SPChangeCollection object that contains a collection of change log entries.

Getting All Changes

The total number of changes returned by a call to the GetChanges method could be very large, depending on the retention period set for the log and the scope at which the call is made. For performance reasons, changes are returned in batches of limited size. Your code should call the GetChanges method in a loop until it returns a collection with zero changes, signifying that it has reached the end of the log.

Each change is stamped with an identifying ChangeToken object, and an SPChangeCollection object has a LastChangeToken property that identifies the last change in the collection. If you pass the LastChangeToken object from the first batch of changes to the GetChanges method when you fetch the second batch, the second batch will pick up changes starting from the point in the log where the previous batch left off. Continue in this fashion until you get an empty collection.

The following example is a simple console application that retrieves all changes from the change log at the content database level.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SPSite site = new SPSite("https://localhost"))
            {
                SPContentDatabase db = site.ContentDatabase;

                // Get the first batch of changes, 
                // starting from the beginning of the log.
                SPChangeCollection changes = db.GetChanges();

                // Loop until the end of the log.
                int total = 0;
                while (changes.Count > 0)
                {
                    total += changes.Count;

                    // Go get another batch.
                    changes = db.GetChanges(changes.LastChangeToken);
                }
                Console.WriteLine("\nTotal changes = {0:#,#}", total);
            }
            Console.Write("\nPress ENTER to continue...");
            Console.Read();
        }
    }
}
Imports System
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.Administration

Module Test

    Sub Main()

        Using site As SPSite = New SPSite("https://localhost")

            Dim db As SPContentDatabase = site.ContentDatabase

            ' Get the first batch of changes, 
            ' starting from the beginning of the log.
            Dim changes As SPChangeCollection = db.GetChanges()

            ' Loop until the end of the log.
            Dim total As Long = 0
            While changes.Count > 0

                total += changes.Count

                ' Go get another batch.
                changes = db.GetChanges(changes.LastChangeToken)

            End While

            Console.WriteLine(vbCrLf + "Total changes: {0:#,#}", total)

        End Using

        Console.Write(vbCrLf + "Press ENTER to continue...")
        Console.ReadLine()

    End Sub

End Module

Reading Part of the Log

You can retrieve changes from a portion of the log by passing two SPChangeToken objects to the GetChanges method. The first change token marks where to begin reading the log; the second marks where to stop.

The following rules apply to the change tokens that are passed as arguments to the GetChanges method.

  • If either token refers to a time before the start of the current change log, the method throws an SPException exception.

  • If the time specified by the second token is earlier than the time specified by the first token, the method returns an empty collection.

  • If the first token is null, the change collection that is returned starts at the beginning of the current change log.

  • If the second token is null, the change collection that is returned includes all changes after the date specified by the first change token, up to the limit for a single collection. If more changes occurred in this period, the first batch is returned.

The following example is a console application that demonstrates how to retrieve changes recorded in the log during a seven day period.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SPSite site = new SPSite("https://localhost"))
            {
                SPContentDatabase db = site.ContentDatabase;

                // Define the start and end dates.
                DateTime startDate = DateTime.UtcNow.AddDays(-30);
                DateTime endDate = startDate.AddDays(7);

                // Build start and end tokens.
                SPChangeToken startToken = new SPChangeToken(
                                                SPChangeCollection.CollectionScope.ContentDB,
                                                db.Id,
                                                startDate);

                SPChangeToken endToken = new SPChangeToken(
                                                SPChangeCollection.CollectionScope.ContentDB,
                                                db.Id,
                                                endDate);

                // Get the first batch of changes.
                SPChangeCollection changes = db.GetChanges(startToken, endToken);

                // Loop until the end of the log.
                int total = 0;
                while (changes.Count > 0)
                {
                    total += changes.Count;

                    // Go get another batch.
                    changes = db.GetChanges(changes.LastChangeToken, endToken);
                }
                Console.WriteLine("\nTotal changes = {0:#,#}", total);
            }
            Console.Write("\nPress ENTER to continue...");
            Console.Read();
        }
    }
}
Imports System
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.Administration

Module Test

    Sub Main()

        Using site As SPSite = New SPSite("https://localhost")

            Dim db As SPContentDatabase = site.ContentDatabase

            ' Define the start and end dates.
            Dim startDate As DateTime = DateTime.UtcNow.AddDays(-30)
            Dim endDate As DateTime = startDate.AddDays(7)

            ' Build start and end tokens.
            Dim startToken As SPChangeToken = New SPChangeToken( _
                                                SPChangeCollection.CollectionScope.ContentDB, _
                                                db.Id, _
                                                startDate)

            Dim endToken As SPChangeToken = New SPChangeToken( _
                                              SPChangeCollection.CollectionScope.ContentDB, _
                                              db.Id, _
                                              endDate)

            ' Get the first batch of changes.
            Dim changes As SPChangeCollection = db.GetChanges(startToken, endToken)

            ' Loop until the end of the log.
            Dim total As Long = 0
            While changes.Count > 0

                total += changes.Count

                ' Go get another batch.
                changes = db.GetChanges(changes.LastChangeToken, endToken)

            End While

            Console.WriteLine(vbCrLf + "Total changes: {0:#,#}", total)

        End Using

        Console.Write(vbCrLf + "Press ENTER to continue...")
        Console.ReadLine()

    End Sub

End Module