Поделиться через


Создание класса контента, который можно заархивировать и восстановить

Дата последнего изменения: 6 мая 2010 г.

Применимо к: SharePoint Foundation 2010

Если требуется добавить настраиваемый компонент в резервные копии Microsoft SharePoint Foundation, следует представить его классом, который реализует интерфейс IBackupRestore. В этом разделе описывается, как это сделать, а также представлен полный пример. (Если компонент — веб-служба, реализующая Платформа приложений служб, есть альтернатива реализации IBackupRestore. Дополнительные сведения см. в разделе Резервное копирование и восстановление в инфраструктуре приложения-службы.)

ПримечаниеПримечание

Если компонент — это база данных, размещенная в Microsoft SQL Server версии Enterprise или Developer, которая должна допускать восстановление из моментального снимка с помощью объектной модели интерфейса пользователя SharePoint Foundation, класс также должен реализовать интерфейс IDatabaseSnapshotRestore. Дополнительные сведения о реализации этого интерфейса см. в разделе Как: Создать класс базы данных, который можно восстанавливать из моментального снимка.

Если компонент состоит из сведений о конфигурации, которые администраторы фермы могут включать в резервные копии конфигурации, см. раздел Практическое руководство. Создание класса, входящего в резервное копирование и восстановление только для конфигураций и следуйте указанным процедурам.

Класс не обязательно должен быть производным от SPPersistedObject, но если содержимое — это база данных, рекомендуется сделать класс производным от SPDatabaseили SPContentDatabase. Оба этих класса являются производными от SPPersistedObject и реализуют IBackupRestore. Поэтому будут доступны стандартные реализации членов IBackupRestore, которые можно использовать при необходимости.

Можно создать столько типов классов IBackupRestore, сколько нужно, и при необходимости они могут быть вложены как дерево классов компонентов. Но наивысший класс в таком дереве должен быть производным (прямо или косвенно) от объекта SPPersistedObject и должен быть дочерним элементом SPFarm. Если класс содержимого не является дочерним объектом какого-либо другого пользовательского класса содержимого, он должен быть производным (прямо или косвенно) от объекта SPPersistedObject и должен быть дочерним элементом SPFarm.

Если класс является производным от класса, который уже реализует объект IBackupRestore (независимо от того, является ли он производным от SPPersistedObject), и нужно заменить наследуемую реализацию члена IBackupRestore, объявление класса должно явно ссылаться на IBackupRestore следующим образом:

[GUID("9573FAD9-ED89-45E8-BD8B-6A5034E03895")]
public class MyClass : SPPersistedObject, IBackupRestore
<System.Runtime.InteropServices.Guid("9573FAD9-ED89-45E8-BD8B-6A5034E03895")>
Public Class [MyClass]
    Inherits SPPersistedObject
    Implements IBackupRestore

End Class
ПримечаниеПримечание

К декларации любого пользовательского класса, напрямую или косвенно наследующего от SPPersistedObject, должен быть применен атрибут GuidAttribute.

"Переопределение" члена IBackupRestore должно явно содержать "IBackupRestore" в имени члена и не должно включать ключевое слово public. Далее показан пример.

UInt64 IBackupRestore.DiskSizeRequired { ... }
Public ReadOnly Property DiskSizeRequired As UInt64 Implements IBackupRestore.DiskSizeRequired
    Get
        ... 
    End Get
End Property

Либо, если реализация члена в родительском классе использовала ключевые слова virtual или override, в реализации можно использовать ключевое слово override следующим образом:

public override UInt64 DiskSizeRequired { ... }
Public Overrides ReadOnly Property DiskSizeRequired() As UInt64
    Get
        ...
    End Get
End Property
Предупреждающая заметкаВнимание!

Не скрывайте наследуемую реализацию члена, повторно объявляя член с помощью new ключевого слова ([new] public UInt64 DiskSizeRequired { ... }) или без него. В представленной далее процедуре подписи членов записываются, как если бы они относились к классу, не являющимся производным от класса, который уже реализует IBackupRestore. Измените их по требуемому шаблону, если класс не является производным от такого родительского элемента.

Если класс является производным от SPPersistedObject, свойства SPPersistedObject.Id и SPPersistedObject.Name этого класса могут служить как реализация свойств IBackupRestore.Id и IBackupRestore.Name. Можно переопределить свойства, но не создавать вторую реализацию какого-либо из этих свойств. Класс должен иметь одно имя и одно свойство Id.

Реализация членов IBackupRestore

  1. Запустите в Visual Studio новый проект класса.

  2. Добавьте ссылку на Microsoft.SharePoint в проекте Visual Studio и добавьте в файл класса операторы using для пространств имен Microsoft.SharePoint.Administration и Microsoft.SharePoint.Administration.Backup.

  3. Если класс не является производным от SPPersistedObject, реализуйте свойство Name. Оно будет служить как имя компонента содержимого в пользовательском интерфейсе stsadm.exe, приложении Центр администрирования и в пользовательском интерфейсе любого пользовательского приложения резервного копирования и восстановления. В большинстве случаев свойство реализуется созданием закрытого поля для значения имени, а закрытое свойство реализуется как оболочка вокруг поля. Сведения о возможных вариантах реализации см. в справочных материалах для свойства.

    private String name;
    public String Name
    {
    get {return name;}
    set {name = value;}
    }
    
     Private _name As String
    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
    
  4. Если класс не является производным от SPPersistedObject, реализуйте свойство Id. В большинстве случаев свойство реализуется созданием частного поля для значения имени, а открытое свойство реализуется как оболочка вокруг поля. Сведения о возможных вариантах реализации см. в описании свойства.

    private Guid id;
    public Guid Id
    {
    get {return id;}
    set {id = value;}
    }
    
    Private _Id As Guid
    Public Property Id() As Guid
        Get
            Return _Id 
        End Get
        Set(ByVal value As Guid)
            _Id = value
        End Set
    End Property
    
  5. Реализуйте свойство DiskSizeRequired. Если класс — это всего лишь контейнер для дочерних классов IBackupRestore, свойство должно возвращать значение 0. В противном случае свойство должно вычислять размер содержимого. (Включая размер объектов, не являющихся потомками IBackupRestore, но не включая размер всех дочерних объектов IBackupRestore. У каждого из них есть собственное свойство DiskSizeRequired, и SharePoint Foundation добавляет эти значения автоматически.) В следующем примере суммируются размеры всех файлов, пути которых содержатся в коллекции FrontEndFilePaths.

    public UInt64 DiskSizeRequired
    {
        get 
        {
            UInt64 total = 0;
            List<FileInfo> FrontEndFiles = new List<FileInfo>(NUMBER_OF_FILES_TO_BACK_UP);
    
            foreach (String path in FrontEndFilePaths)
            {
                FileInfo file = new FileInfo(path);
                FrontEndFiles.Add(file);
            }
    
            foreach (FileInfo file in FrontEndFiles)
            {
                total = total + (UInt64)file.Length;
            }
    
            return total;
        }
    } 
    
    Public ReadOnly Property DiskSizeRequired() As UInt64 Implements IBackupRestore.DiskSizeRequired
        Get
            Dim total As UInt64 = 0
            Dim FrontEndFiles As New List(Of FileInfo)(NUMBER_OF_FILES_TO_BACK_UP)
    
            For Each path As String In FrontEndFilePaths
                Dim file As New FileInfo(path)
                FrontEndFiles.Add(file)
            Next path
    
            For Each file As FileInfo In FrontEndFiles
                total = total + CULng(file.Length)
            Next file
    
            Return total
        End Get
    End Property
    
  6. Реализуйте свойство CanSelectForBackup. Если пользователи никогда не должны иметь возможности создавать резервные копии объектов класса независимо от резервной копии родительского объекта, метод доступа get должен возвращать значение false. Если пользователи должны всегда иметь возможность выбирать любой объект класса для независимого резервного копирования, метод доступа get должен возвращать true. В любом случае метод доступа set должен быть пустой парой фигурных скобок "{ }". Если резервное копирование для некоторых объектов класса может выполняться независимо от родительского объекта, а для других — нет, реализуйте свойство как оболочку вокруг частного поля Boolean.

  7. Реализуйте свойство CanSelectForRestore. Если пользователи никогда не должны иметь возможности восстанавливать объекты класса пользовательского компонента независимо от восстановления родительского объекта, метод доступа get должен возвращать значение false. Если пользователи должны всегда иметь возможность выбирать любой объект класса для независимого восстановления, метод доступа get должен возвращать true. В любом случае метод доступа set должен быть пустой парой фигурных скобок "{ }". Если восстановление для некоторых объектов класса может выполняться независимо от родительского объекта, а для других — нет, реализуйте свойство как оболочку вокруг частного поля Boolean.

  8. Реализуйте свойство CanRenameOnRestore. Если пользователи никогда не могут восстанавливать объекты настраиваемого класса компонентов в новое место, метод доступа get должен возвращать false. Если пользователи могут переносить любые объекты класса, метод доступа get должен возвращать true. Если объекты класса могут перемещаться иногда, но не всегда, реализуйте свойство как оболочку вокруг частного поля Boolean.

  9. Реализуйте метод AddBackupObjects(SPBackupRestoreObject).

    1. Код реализации должен начинаться с вызова исключения, если нет действительного родительского объекта, к которому может быть добавлен компонент.

    2. Метод AddChild используется для добавления компонента к дереву объектов, которое будет обрабатываться во время операции резервного копирования или восстановления.

    3. Метод SetParameter(String, Object) используется для задания имени типа и описания компонента, который может быть использован пользовательским интерфейсом приложений резервного копирования и восстановления.

    4. Если компонент имеет дочерние объекты IBackupRestore, реализация должна выполнять итерацию по ним и рекурсивно вызывать метод AddBackupObjects(SPBackupRestoreObject) каждого дочернего объекта.

    5. Дополнительные сведения о реализации метода AddBackupObjects(SPBackupRestoreObject) см. в справочных материалах по этому методу.

    В следующем примере кода предполагается, что в классе содержимого есть коллекция ChildContentCollection дочерних объектов IBackupRestore. Если в классе несколько типов дочернего компонента, можно иметь отдельные коллекции для каждого типа и выполнять итерацию по каждой коллекции.

    public void AddBackupObjects(SPBackupRestoreObject parent)
    {
        if (parent == null)
        {
            throw new ArgumentNullException("parent");
        }
    
        SPBackupRestoreObject self = parent.AddChild(this);
        self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, this.GetType());
        self.Information.SetParameter(SPBackupRestoreObject.SPDescription,
        "Description of custom content component");
    
        foreach (ChildContent child in ChildContentCollection)
        {
            IBackupRestore childIBR = child as IBackupRestore;
            childIBR.AddBackupObjects(self);
        }
    }
    
    Public Sub AddBackupObjects(ByVal parent As SPBackupRestoreObject) Implements IBackupRestore.AddBackupObjects
        If parent Is Nothing Then
            Throw New ArgumentNullException("parent")
        End If
    
        Dim self As SPBackupRestoreObject = parent.AddChild(Me)
        self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, Me.GetType())
        self.Information.SetParameter(SPBackupRestoreObject.SPDescription, "Description of custom content component")
    
        For Each child As ChildContent In ChildContentCollection
            Dim childIBR As IBackupRestore = TryCast(child, IBackupRestore)
            childIBR.AddBackupObjects(self)
        Next child
    End Sub
    
  10. Реализуйте метод OnAbort(Object, SPBackupRestoreInformation). Он должен всегда возвращать true. В большинстве случаев он ничего больше не должен делать, но для получения сведений об исключениях из этого общего правила см. справочный материал для OnAbort(Object, SPBackupRestoreInformation).

  11. Реализуйте метод OnPrepareBackup(Object, SPBackupInformation). Как минимум метод SetParameter(String, Object) должен использоваться для задания имени объекта содержимого. Кроме того, может быть сделан ряд обобщений. Дополнительные сведения см. в справочных материалах OnPrepareBackup(Object, SPBackupInformation). В следующем примере показана минимальная реализация метода, которой чаще всего оказывается достаточно.

    public Boolean OnPrepareBackup(Object sender, SPBackupInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.SetParameter(SPBackupRestoreObject.SPName, this.Name);
        return true;
    }
    
    Public Function OnPrepareBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnPrepareBackup 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.SetParameter(SPBackupRestoreObject.SPName, Me.Name)
        Return True
    End Function
    
  12. Реализуйте метод OnBackup. Если класс содержимого не имеет содержимого вне дочерних объектов IBackupRestore, которые могут у него быть, реализация должна просто присваивать CurrentProgress значение, которое приблизительно представляет долю в процентах от общего времени резервного копирования, которое приходится на работы методов OnBackup(Object, SPBackupInformation) и OnPrepareBackup(Object, SPBackupInformation). Он должен возвращать true, как видно из следующего примера. Не вызывайте метод OnBackup(Object, SPBackupInformation) какого-либо из дочерних объектов IBackupRestore.

    public Boolean OnBackup(Object sender, SPBackupInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.CurrentProgress = 50;
        return true;
    }
    
    Public Function OnBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnBackup 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 50
        Return True
    End Function
    

    Если класс имеет содержимое вне дочерних объектов IBackupRestore, которые могут у него быть, реализация должна копировать это содержимое в args.Location и возвращать false, если копирование закончится ошибкой. Нужно включить правила для резервного копирования дочерних объектов, которые не реализуют IBackupRestore, но нельзя явно выполнять резервное копирование дочерних объектов, которые реализуютIBackupRestore. Их резервное копирование будет выполнено их собственным методом OnBackup(Object, SPBackupInformation), который вызовет среда выполнения. Нельзя вызывать методы OnBackup(Object, SPBackupInformation) дочерних объектов в своем собственном коде. В следующем примере показана общая структура самостоятельной реализации OnBackup(Object, SPBackupInformation).

    public Boolean OnBackup(Object sender, SPBackupInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.CurrentProgress = 50;
        Boolean successSignal = true;
    
        // TODO: Implement copying your content to args.Location
        //       If the copy fails, set successSignal to false.
    
        return successSignal;
    }
    
    Public Function OnBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnBackup 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 50
        Dim successSignal As Boolean = True
    
        ' TODO: Implement copying your content to args.Location
        '       If the copy fails, set successSignal to false.
    
        Return successSignal
    End Function
    
  13. Реализуйте метод OnBackupComplete. Как минимум реализация должна установить для CurrentProgress значение 100 процентов и возвратить true, как показано в следующем примере. Обычно только это и нужно. Сведения о других действиях реализации, которые могут понадобиться, см. в справочном материале по OnBackupComplete(Object, SPBackupInformation).

    public Boolean OnBackupComplete(Object sender, SPBackupInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.CurrentProgress = 100;
        return true;
    }
    
    Public Function OnBackupComplete(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnBackupComplete 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 100
        Return True
    End Function
    
  14. Реализуйте метод OnPreRestore. В большинстве случаев для операции восстановления подготовка не нужна, и реализация OnPreRestore должна только возвратить true. Сведения о других действиях реализации, которые могут понадобиться, см. в справочном материале по OnPreRestore.

  15. Реализуйте метод OnRestore.

    • Если класс содержимого можно переносить, код должен проверять, какой метод восстановления используется и вызывать Rename(), если методом является New.

    • Если класс содержимого не имеет содержимого вне дочерних объектов IBackupRestore, которые могут у него быть, реализация должна просто присваивать CurrentProgress значение, которое приблизительно представляет долю в процентах от общего времени резервного копирования, которое приходится на работу методов OnRestore и OnPreRestore. Она должна возвратить true, как показано в следующем примере. Не вызывайте метод OnRestore какого-либо из дочерних объектов IBackupRestore.

    public Boolean OnRestore(Object sender, SPRestoreInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        if (args.RestoreMethod == SPRestoreMethodType.New)
        {
            args.Rename();
        }
        args.CurrentProgress = 50;
        return true;
    }
    
    Public Function OnRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean implements IBackupRestore.OnRestore 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        If args.RestoreMethod = SPRestoreMethodType.New Then
            args.Rename()
        End If
        args.CurrentProgress = 50
        Return True
    End Function
    
    • Если класс имеет содержимое вне дочерних объектов IBackupRestore, которые могут у него быть, реализация должна копировать это содержимое в местоположение восстановления. Возвращается false, если по какой-либо причине копирование заканчивается ошибкой.

    В следующем примере показана общая структура самостоятельной реализации OnRestore.

    public Boolean OnRestore(Object sender, SPRestoreInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        if (args.RestoreMethod == SPRestoreMethodType.New)
        {
            args.Rename();
        }
        args.CurrentProgress = 50;
        Boolean successSignal = true;
    
        // TODO: Implement copying your content to the destination.
        //       If the copy fails, set successSignal to false.
    
        return successSignal;
    }
    
    Public Function OnRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean implements IBackupRestore.OnRestore 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        If args.RestoreMethod = SPRestoreMethodType.New Then
            args.Rename()
        End If
        args.CurrentProgress = 50
        Dim successSignal As Boolean = True
    
        ' TODO: Implement copying your content to the destination.
        '       If the copy fails, set successSignal to false.
    
        Return successSignal
    End Function
    
  16. Реализуйте метод OnPostRestore. Как минимум реализация должна установить для CurrentProgress значение 100 процентов и возвратить true, как показано в следующем примере. Обычно только это и нужно. Сведения о других действиях реализации, которые могут понадобиться, см. в справочном материале по OnPostRestore.

    public Boolean OnPostRestore(Object sender, SPRestoreInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.CurrentProgress = 100;
        return true;
    }
    
    Public Function OnPostRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean implements IBackupRestore.OnPostRestore 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 100
        Return True
    End Function
    

Добавление всех других членов класса

  1. Добавьте поля, свойства и вспомогательные методы, необходимые для полноты класса. При работе следует учитывать следующее.

    • Используйте поля и свойства для размещения дочерних объектов содержимого.

    • Если класс является производным от SPPersistedObject, перед объявлениями полей, которые должны быть неизменными в базе данных настроек, должен стоять атрибут [Persisted]. Однако таким образом можно пометить только следующие типы полей: примитивные типы, такие как строки, целые числа и идентификаторы GUID; другие объекты SPPersistedObject или объекты SPAutoserializingObject; либо коллекции указанных выше элементов. Например, класс не может иметь поле FileInfo, помеченное атрибутом [Persisted]. Если данные, которые должны быть постоянными, не относятся к постоянному классу, выполните замену для обеспечения постоянности. Образец реализации свойства DiskSizeRequired дает представление о классе, который сохраняет неизменной коллекцию имен файлов и использует их для создания временной коллекции объектов FileInfo в среде выполнения.

    • Если класс может иметь несколько дочерних элементов одного типа, создайте свойство или поле типа коллекции или другого перечисляемого типа для хранения коллекции всех дочерних объектов данного типа. Это особенно важно, если тип дочернего объекта сам реализует IBackupRestore, поскольку реализация метода AddBackupObjects(SPBackupRestoreObject) должна выполнять итерацию по таким дочерним объектам и вызывать метод AddBackupObjects(SPBackupRestoreObject) каждого дочернего объекта. Дополнительные сведения см. в описании части процедуры, касающейся реализации указанного выше метода AddBackupObjects(SPBackupRestoreObject).

  2. Добавьте в класс конструкторы для инициализации его полей и свойств, если необходимо. Если класс является производным от SPPersistedObject, должен быть хотя бы один конструктор, который именует объект и назначает его родительскому объекту. Обычно такой конструктор принимает по крайней мере два аргумента:

    • аргумент String, который является именем объекта содержимого;

    • аргумент SPPersistedObject, который представляет родительский объект объекта содержимого.

    Этот конструктор должен вызывать базовый конструктор, который принимает те же два аргумента. Далее представлен пример.

    public MyContentComponent(String componentName, SPPersistedObject parent, SomeTypesomeOtherArgument, ... ) 
                       : base(componentName, parent)
    {
        somePrivateField = someOtherArgument;
        ...
    }
    
    Public Sub New(ByVal componentName As String, ByVal parent As SPPersistedObject, ByVal someOtherArgument As SomeType, . ByVal .. As )
        MyBase.New(componentName, parent)
        somePrivateField = someOtherArgument
       ...
    End Sub
    

    Необходимо передать SPFarm.Local как родительский объект, если объект содержимого является самым верхним объектом в дереве пользовательских объектов IBackupRestore. Если тип пользовательского компонента всегда является самым верхним объектом, опустите аргумент SPPersistedObject и внесите непосредственно в код ссылку на SPFarm.Local в вызове базового конструктора. Далее представлен пример.

    public MyContentComponent(String componentName, SomeTypesomeOtherArgument, ... ) 
                       : base(componentName, SPFarm.Local)
    {
        somePrivateField = someOtherArgument;
        ...
    }
    
    Public Sub New(ByVal componentName As String, ByVal someOtherArgument As SomeType, . ByVal .. As )
        MyBase.New(componentName, SPFarm.Local)
        somePrivateField = someOtherArgument
       ...
    End Sub
    

    Если объекты класса всегда имеют одно и то же имя, можно опустить аргумент String и записать в коде имя в вызове базового конструктора. (Если все объекты данного типа имеют одно и то же имя, никогда не может быть нескольких дочерних объектов этого типа для конкретного родительского объекта; таким образом, если объект является дочерним объектом фермы, во всей ферме может быть только один объект этого типа.)

  3. Скомпилируйте проект класса.

    Предупреждающая заметкаВнимание!

    Сборке необходимо дать строгое имя и поместить ее в глобальный кэш сборок (GAC).

Создание объекта класса и помещение его в ферму как дочерний объект

  1. Запустите новый проект консольного приложения в Visual Studio.

  2. Добавьте в проекте ссылку на библиотеку DLL настраиваемых классов компонентов.

  3. Добавьте using выражение для Microsoft.SharePoint.Administration.

  4. Добавьте выражение using для пространства имен, используемого в настраиваемом классе компонентов (или просто используйте в консольном приложении то же пространство имен).

  5. Добавьте в метод Main проекта вызов конструктора настраиваемого класса компонентов. Если создана иерархия настраиваемых типов, вызывайте конструктор в самом верхнем классе.

  6. Если необходимо, введите перед вызовом конструктора компонента код, который создает параметры для конструктора.

  7. После вызова конструктора компонента в коде должен быть вызов метода Update объекта компонента. Далее показан пример, что должно быть в методе Main.

    MyContentComponent myContentObject = new MyContentComponent("component name", SPFarm.Local);
    myContentObject.Update();
    
    Dim myContentObject As New MyContentComponent("component name", SPFarm.Local)
    myContentObject.Update()
    
  8. Скомпилируйте и запустите приложение.

  9. В приложении центра администрирования последовательно выберите Операции | Выполнить резервное копирование. Объект должен отображаться как дочерний объект фермы на странице Выполнение резервного копирования.

    ПримечаниеПримечание

    В представленном ниже разделе Пример приведен образец консольного приложения для создания и удаления пользовательских объектов содержимого.

Советы при разработке

Вероятно, что в ходе работы много раз будут создаваться объекты, которые затем будут добавляться в ферму. Поэтому при разработке пользовательских классов содержимого могут быть полезны следующие советы.

Моменты, которые следует иметь в виду

  1. Если нужно удалить объект из базы данных настроек, используйте Delete().

  2. При вызове obj.Update(), если уже есть объект того же класса, что и obj с тем же значением свойства Name и с тем же родительским объектом в базе данных, может быть сгенерировано исключение. Имеется перегруженная версия Update, которая может оказаться предпочтительней.

  3. В представленном далее втором разделе Пример имеется образец консольного приложения. Его можно использовать для добавления настраиваемых объектов в базу данных настроек или удаления этих объектов из базы данных.

  4. Запускайте iisreset в командной строке после каждой перекомпиляции класса IBackupRestore. Может также понадобиться перезагрузка сервера.

  5. Различные методы IBackupRestore.On* принимают либо параметр SPBackupInformation, либо параметр SPRestoreInformation. Их членов можно использовать для отладки. Особенно полезным является метод Log.

Пример

Следующий код реализует пользовательский компонент содержимого, который представляет один файл Web.config на интерфейсном сервере. Замените часть TestSite пути файла в реализации конструктора на имя каталога тестового сервера. Скомпилированная сборка должна иметь строгое имя и быть установлена в GAC.

В примере реализации класса имеется код простого консольного приложения, которое будет регистрировать компонент как дочерний объект фермы или удалять его из фермы.

using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Backup;

namespace MyCompany.SharePoint.Administration
{
    public class CriticalFiles : SPPersistedObject, IBackupRestore
    {

        public CriticalFiles() { }

        public CriticalFiles(String componentName, SPPersistedObject parent) 
                   : base(componentName, parent)
        {
            String pathOfFile = @"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\TestSite\Web.config";
            FrontEndFilePaths.Add(pathOfFile);
        }

        [Persisted]
        private const Int32 NUMBER_OF_FILES_TO_BACK_UP = 1;

        [Persisted]
        private List<String> FrontEndFilePaths = new List<String>(NUMBER_OF_FILES_TO_BACK_UP);

        public Boolean CanSelectForBackup
        {
            get { return true; }
            set { }
        }

        public Boolean CanSelectForRestore
        {
            get { return true; }
            set { }
        }

        public Boolean CanRenameOnRestore
        {
            get { return false; }
        }

        public UInt64 DiskSizeRequired
        {
            get
            {
                UInt64 total = 0;
                List<FileInfo> FrontEndFiles = new List<FileInfo>(NUMBER_OF_FILES_TO_BACK_UP);
                
                foreach (String path in FrontEndFilePaths)
                {
                    FileInfo file = new FileInfo(path);
                    FrontEndFiles.Add(file);
                }
                
                foreach (FileInfo file in FrontEndFiles)
                {
                    total = total + (UInt64)file.Length;
                }
                
                return total;
            }
        }

        public void AddBackupObjects(SPBackupRestoreObject parent)
        {
            if (parent == null)
            {
                throw new ArgumentNullException("parent");
            }

            SPBackupRestoreObject self = parent.AddChild(this);
            self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, this.GetType());
            self.Information.SetParameter(SPBackupRestoreObject.SPDescription, "The critical files on all front end servers.");
        }

        public Boolean OnAbort(Object sender, SPBackupRestoreInformation args)
        {
            return true;
        }

        public Boolean OnPrepareBackup(Object sender, SPBackupInformation args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            args.SetParameter(SPBackupRestoreObject.SPName, this.Name);
            return true;
        }

        public Boolean OnBackup(Object sender, SPBackupInformation args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            
            Boolean successSignal = true;

            foreach (String path in FrontEndFilePaths)
            {
                FileInfo file = new FileInfo(path);
                try
                {
                    String mappedFileName = args.GenerateFileMapping(file.Name);
                    file.CopyTo(args.Location + @"\" + mappedFileName, true);
                    args.Log(SPBackupRestoreLogSeverity.Verbose, "Backed up " + file.Name + " in (" + mappedFileName + ")");
                }
                catch (Exception e)
                {
                    args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name + " not backed up: " + e.Message);
                    successSignal = false;
                }
            }

            args.CurrentProgress = 50;
            return successSignal;
        }

        public Boolean OnBackupComplete(Object sender, SPBackupInformation args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            args.CurrentProgress = 100;
            return true;
        }

        public Boolean OnPreRestore(Object sender, SPRestoreInformation args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            return true;
        }

        public Boolean OnRestore(Object sender, SPRestoreInformation args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            // If the CriticalFiles object was deleted from the farm after it was
            // backed up, restore it to the configuration database.
            CriticalFiles cf = SPFarm.Local.GetChild<CriticalFiles>(this.Name);
            if (cf == null)
            {
                this.Update();
                args.Log(SPBackupRestoreLogSeverity.Verbose, this.Name + " added back to configuration database.");
            }

            Boolean successSignal = true;

            // TODO: The following loop restores files to the local server. If there are 
            //       multiple front end servers, your code must iterate through all of 
            //       SPFarm.Local.Servers and restore the same files to every server whose
            //       Role property is SPServerRole.WebFrontEnd

            foreach (String path in FrontEndFilePaths)
            {
                FileInfo backupCopy = new FileInfo(path);
                String mappedFileName = args.ReverseFileMapping(backupCopy.Name);
                FileInfo file = new FileInfo(args.Location + @"\" + mappedFileName);

                try
                {
                    file.CopyTo(path, true);
                    args.Log(SPBackupRestoreLogSeverity.Verbose, "Restored " + backupCopy.Name);
                }
                catch (Exception e)
                {
                    args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name + " not restored: " + e.Message);
                    successSignal = false;
                }
            }
            
            args.CurrentProgress = 50;
            return successSignal;
        }
        
        public Boolean OnPostRestore(Object sender, SPRestoreInformation args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            args.CurrentProgress = 100;
            return true;
        }

    }
}
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports Microsoft.SharePoint.Administration
Imports Microsoft.SharePoint.Administration.Backup


Namespace MyCompany.SharePoint.Administration
    Public Class CriticalFiles
        Inherits SPPersistedObject
        Implements IBackupRestore

        Public Sub New()
        End Sub

        Public Sub New(ByVal componentName As String, ByVal parent As SPPersistedObject)
            MyBase.New(componentName, parent)
            Dim pathOfFile As String = "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\TestSite\Web.config"
            FrontEndFilePaths.Add(pathOfFile)
        End Sub

        <Persisted()>
        Private Const NUMBER_OF_FILES_TO_BACK_UP As Int32 = 1

        <Persisted()>
        Private FrontEndFilePaths As New List(Of String)(NUMBER_OF_FILES_TO_BACK_UP)

        Public Property CanSelectForBackup() As Boolean Implements IBackupRestore.CanSelectForBackup
            Get
                Return True
            End Get
            Set(ByVal value As Boolean)
            End Set
        End Property

        Public Property CanSelectForRestore() As Boolean Implements IBackupRestore.CanSelectForRestore
            Get
                Return True
            End Get
            Set(ByVal value As Boolean)
            End Set
        End Property

        Public ReadOnly Property CanRenameOnRestore() As Boolean Implements IBackupRestore.CanRenameOnRestore
            Get
                Return False
            End Get
        End Property

        Public ReadOnly Property DiskSizeRequired() As UInt64 Implements IBackupRestore.DiskSizeRequired
            Get
                Dim total As UInt64 = 0
                Dim FrontEndFiles As New List(Of FileInfo)(NUMBER_OF_FILES_TO_BACK_UP)

                For Each path As String In FrontEndFilePaths
                    Dim file As New FileInfo(path)
                    FrontEndFiles.Add(file)
                Next path

                For Each file As FileInfo In FrontEndFiles
                    total = total + CULng(file.Length)
                Next file

                Return total
            End Get
        End Property

        Public Sub AddBackupObjects(ByVal parent As SPBackupRestoreObject) Implements IBackupRestore.AddBackupObjects
            If parent Is Nothing Then
                Throw New ArgumentNullException("parent")
            End If

            Dim self As SPBackupRestoreObject = parent.AddChild(Me)
            self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, Me.GetType())
            self.Information.SetParameter(SPBackupRestoreObject.SPDescription, "The critical files on all front end servers.")
        End Sub

        Public Function OnAbort(ByVal sender As Object, ByVal args As SPBackupRestoreInformation) As Boolean Implements IBackupRestore.OnAbort
            Return True
        End Function

        Public Function OnPrepareBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean Implements IBackupRestore.OnPrepareBackup
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If
            args.SetParameter(SPBackupRestoreObject.SPName, Me.Name)
            Return True
        End Function

        Public Function OnBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean Implements IBackupRestore.OnBackup
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If

            Dim successSignal As Boolean = True

            For Each path As String In FrontEndFilePaths
                Dim file As New FileInfo(path)
                Try
                    Dim mappedFileName As String = args.GenerateFileMapping(file.Name)
                    file.CopyTo(args.Location & "\" & mappedFileName, True)
                    args.Log(SPBackupRestoreLogSeverity.Verbose, "Backed up " & file.Name & " in (" & mappedFileName & ")")
                Catch e As Exception
                    args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name & " not backed up: " & e.Message)
                    successSignal = False
                End Try
            Next path

            args.CurrentProgress = 50
            Return successSignal
        End Function

        Public Function OnBackupComplete(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean Implements IBackupRestore.OnBackupComplete
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If
            args.CurrentProgress = 100
            Return True
        End Function

        Public Function OnPreRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If
            Return True
        End Function

        Public Function OnRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean Implements IBackupRestore.OnRestore
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If

            ' If the CriticalFiles object was deleted from the farm after it was
            ' backed up, restore it to the configuration database.
            Dim cf As CriticalFiles = SPFarm.Local.GetChild(Of CriticalFiles)(Me.Name)
            If cf Is Nothing Then
                Me.Update()
                args.Log(SPBackupRestoreLogSeverity.Verbose, Me.Name & " added back to configuration database.")
            End If

            Dim successSignal As Boolean = True

            ' TODO: The following loop restores files to the local server. If there are 
            '       multiple front end servers, your code must iterate through all of 
            '       SPFarm.Local.Servers and restore the same files to every server whose
            '       Role property is SPServerRole.WebFrontEnd

            For Each path As String In FrontEndFilePaths
                Dim backupCopy As New FileInfo(path)
                Dim mappedFileName As String = args.ReverseFileMapping(backupCopy.Name)
                Dim file As New FileInfo(args.Location & "\" & mappedFileName)

                Try
                    file.CopyTo(path, True)
                    args.Log(SPBackupRestoreLogSeverity.Verbose, "Restored " & backupCopy.Name)
                Catch e As Exception
                    args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name & " not restored: " & e.Message)
                    successSignal = False
                End Try
            Next path

            args.CurrentProgress = 50
            Return successSignal
        End Function

        Public Function OnPostRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean Implements IBackupRestore.OnPostRestore
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If

            args.CurrentProgress = 100
            Return True
        End Function

    End Class
End Namespace

Далее показано консольное приложение, которое добавляет объект содержимого в базу данных конфигураций или удаляет такой объект из базы данных.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Backup;

namespace MyCompany.SharePoint.Administration
{
    class Program 
    {
        static void Main(string[] args)
        {
            CriticalFiles cf = SPFarm.Local.GetChild<CriticalFiles>("Critical Front End Files");
            if (cf == null)
            {
                Console.WriteLine("There is no CriticalFiles object in the configuration database.");
                Console.Write("Enter 'A' to add it. Press Return to do nothing:");
                String response = Console.ReadLine();
                if (response == "A")
                {
                    CriticalFiles myCriticalFiles = new CriticalFiles("Critical Front End Files", SPFarm.Local);
                    myCriticalFiles.Update();
                }
            }
            else
            {
                Console.WriteLine("There is a CriticalFiles object in the configuration database.");
                Console.Write("Enter 'D' to delete it. Press Return to do nothing:");
                String response = Console.ReadLine();
                if (response == "D")
                {
                    cf.Delete();
                }
            }
        }// end Main
    }// end Program
} 
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Microsoft.SharePoint.Administration
Imports Microsoft.SharePoint.Administration.Backup

Namespace MyCompany.SharePoint.Administration
    Module Program
        Sub Main(ByVal args() As String)
            Dim cf As CriticalFiles = SPFarm.Local.GetChild(Of CriticalFiles)("Critical Front End Files")
            If cf Is Nothing Then
                Console.WriteLine("There is no CriticalFiles object in the configuration database.")
                Console.Write("Enter 'A' to add it. Press Return to do nothing:")
                Dim response As String = Console.ReadLine()
                If response = "A" Then
                    Dim myCriticalFiles As New CriticalFiles("Critical Front End Files", SPFarm.Local)
                    myCriticalFiles.Update()
                End If
            Else
                Console.WriteLine("There is a CriticalFiles object in the configuration database.")
                Console.Write("Enter 'D' to delete it. Press Return to do nothing:")
                Dim response As String = Console.ReadLine()
                If response = "D" Then
                    cf.Delete()
                End If
            End If
        End Sub ' end Main
    End Module  ' end Program
End Namespace

См. также

Задачи

Программное резервное копирование контента

Программное восстановление контента

Программное резервное копирование и восстановление одного семейства сайтов

Как: Создать класс базы данных, который можно восстанавливать из моментального снимка

Практическое руководство. Создание класса, входящего в резервное копирование и восстановление только для конфигураций

Ссылка

Microsoft.SharePoint.Administration.Backup

Backup

Restore

Концепции

Программирование с использованием объектной модели резервного копирования и восстановления SharePoint Foundation