从更改日志获取更改

上次修改时间: 2009年7月29日

适用范围: SharePoint Foundation 2010

可以通过调用 SPListSPWebSPSiteSPContentDatabase 对象的 GetChanges 方法,以编程方式访问更改日志。在这些范围内进行的调用是逐次包含的。在每种情况下,GetChanges 方法都将返回包含更改日志项的集合的 SPChangeCollection 对象。

获取所有更改

调用 GetChanges 方法返回的更改总数会非常大,具体取决于为日志设置的保留时间和执行调用的范围。出于性能方面的原因,会将更改分为多个大小有限的批次返回。您的代码将循环调用 GetChanges 方法直至返回无更改的集合,这表示它已到达日志结尾处。

用标识 ChangeToken 对象来标记每个更改,并且 SPChangeCollection 对象具有一个 LastChangeToken 属性,该属性标识集合中最后的更改。如果在获取第二个批次时将 LastChangeToken 对象从更改的第一个批次传递到 GetChanges 方法,则第二个批次将从日志中前一个批次的停止处开始获取更改。按照此方式继续操作,直到您得到一个空集合。

下面的示例是一个简单的控制台应用程序,该应用程序从更改日志中检索内容数据库级别的所有更改。

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

阅读日志的部分内容

可以通过将两个 SPChangeToken 对象传递给 GetChanges 方法,从日志的部分内容中检索更改。第一个更改标记将标识开始阅读日志的位置;第二个更改标记将标识停止位置。

下面的规则适用于作为参数传递到 GetChanges 方法的更改标记。

  • 如果任一标记指定当前更改日志开始前的某个时间,则此方法将引发 SPException 异常。

  • 如果第二个标记指定的时间早于第一个标记指定的时间,则此方法将返回空集合。

  • 如果第一个标记为 null,则返回的更改集合将从当前更改日志的开头开始。

  • 如果第二个标记为 null,则返回的更改集合将包含第一个更改标记指定的日期之后发生的所有更改(直到达到单个集合的限制)。如果此时间段内发生多个更改,则返回第一个批次。

下面的示例是一个控制台应用程序,此应用程序演示如何检索七天时间内日志中记录的更改。

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