Gewusst wie: Erstellen einer Inhaltsklasse, die gesichert und wiederhergestellt werden kann
Letzte Änderung: Donnerstag, 6. Mai 2010
Gilt für: SharePoint Foundation 2010
Wenn Sie eine benutzerdefinierte Inhaltskomponente in Microsoft SharePoint Foundation-Sicherungen und -Wiederherstellungen einschließen möchten, müssen Sie die Komponente durch eine Klasse darstellen, mit der die IBackupRestore-Schnittstelle implementiert wird. Die Vorgehensweise wird in diesem Thema erläutert. Im Anschluss an die Verfahren finden Sie ein vollständiges Beispiel. (Wenn es sich bei der Komponente um einen Webdienst handelt, durch den das Service Application Framework implementiert wird, gibt es eine Alternative zum Implementieren von IBackupRestore. Weitere Informationen finden Sie unter Sicherung und Wiederherstellen in Service Application Framework.)
Hinweis |
---|
Wenn es sich bei der Komponente um eine in den Enterprise- oder Developer-Editionen von Microsoft SQL Server gehostete Datenbank handelt, deren Wiederherstellung über die Benutzeroberfläche oder das Objektmodell von SharePoint Foundation aus einer Momentaufnahme möglich sein soll, muss von der Klasse auch die IDatabaseSnapshotRestore-Schnittstelle implementiert werden. Weitere Informationen zum Implementieren dieser Schnittstelle finden Sie unter Gewusst wie: Erstellen einer Datenbankklasse, die aus einem Snapshot wiederhergestellt werden kann. Wenn die Komponente aus Konfigurationsinformationen besteht, die Farmadministratoren wahlweise in Sicherungen und Wiederherstellungen nur der Konfiguration einschließen können sollen, lesen Sie das Thema Gewusst wie: Erstellen einer Klasse, die in reine Konfigurationssicherungen und -wiederherstellungen einbezogen wird, und führen Sie gegebenenfalls das dort beschriebene Verfahren aus. |
Die Klasse muss nicht von SPPersistedObject abgeleitet werden. Wenn es sich beim Inhalt jedoch um eine Datenbank handelt, wird empfohlen, die Klasse von SPDatabase oder von SPContentDatabase abzuleiten. Diese beiden Klassen werden von SPPersistedObject abgeleitet und implementieren IBackupRestore. Daher erhalten Sie Standardimplementierungen von Membern von IBackupRestore, die Sie gegebenenfalls verwenden können.
Sie können beliebig viele Typen von IBackupRestore-Klassen erstellen, die bei Bedarf als Struktur aus Komponentenklassen geschachtelt werden können. Die höchste Klasse in einer solchen Struktur muss jedoch (direkt oder indirekt) vom SPPersistedObject-Objekt abgeleitet werden und muss eine untergeordnete Klasse von SPFarm sein. Wenn es sich bei der Inhaltsklasse nicht um eine untergeordnete Klasse einer anderen benutzerdefinierten Inhaltsklasse handelt, muss die Klasse (direkt oder indirekt) vom SPPersistedObject-Objekt abgeleitet werden und muss eine untergeordnete Klasse von SPFarm sein.
Wenn die Klasse von einer Klasse abgeleitet wird, von der das IBackupRestore-Objekt bereits implementiert wird (unabhängig davon, ob dieses von SPPersistedObject abgeleitet wird), und Sie eine geerbte Implementierung eines IBackupRestore-Members ersetzen möchten, sollte die Klassendeklaration explizit wie hier gezeigt auf IBackupRestore verweisen:
[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
Hinweis |
---|
Auf die Deklaration jeder benutzerdefinierten Klasse, die direkt oder indirekt von SPPersistedObject erbt, muss GuidAttribute angewendet werden. |
Die Außerkraftsetzung eines IBackupRestore-Members sollte explizit "IBackupRestore" im Membernamen enthalten und sollte nicht das public-Schlüsselwort enthalten. Der folgende Code ist ein Beispiel dafür.
UInt64 IBackupRestore.DiskSizeRequired { ... }
Public ReadOnly Property DiskSizeRequired As UInt64 Implements IBackupRestore.DiskSizeRequired
Get
...
End Get
End Property
Alternativ können Sie, wenn für die Implementierung des Members in der übergeordneten Klasse die Schlüsselwörter virtual oder override verwendet wurden, wie hier gezeigt in der Implementierung das override-Schlüsselwort verwenden:
public override UInt64 DiskSizeRequired { ... }
Public Overrides ReadOnly Property DiskSizeRequired() As UInt64
Get
...
End Get
End Property
Vorsicht |
---|
Blenden Sie die geerbte Memberimplementierung nicht aus, indem Sie den Member mit oder ohne dem new-Schlüsselwort ([new] public UInt64 DiskSizeRequired { ... }) erneut deklarieren. Im unten gezeigten Verfahren werden die Membersignaturen so geschrieben wie für eine Klasse, die nicht von einer Klasse abgeleitet wird, von der IBackupRestore bereits implementiert wird. Ändern Sie die Membersignaturen unbedingt in das erforderliche Muster, wenn die Klasse nicht von einer solchen übergeordneten Klasse abgeleitet wird. |
Wenn die Klasse von SPPersistedObject abgeleitet wird, verwenden Sie die Eigenschaften SPPersistedObject.Id und SPPersistedObject.Name dieser Klasse als Implementierung der Eigenschaften IBackupRestore.Id und IBackupRestore.Name. Sie können die Eigenschaften außer Kraft setzen, erstellen Sie aber keine zweite Implementierung der Eigenschaften. Die Klasse sollte nur eine Name-Eigenschaft und eine Id-Eigenschaft haben.
So implementieren Sie die Member von "IBackupRestore"
Beginnen Sie ein neues Klassenprojekt in Visual Studio.
Fügen Sie dem Visual Studio-Projekt einen Verweis auf Microsoft.SharePoint hinzu, und fügen Sie der Klassendatei using-Anweisungen für die Namespaces Microsoft.SharePoint.Administration und Microsoft.SharePoint.Administration.Backup hinzu.
Wenn die Klasse nicht von SPPersistedObject abgeleitet wird, implementieren Sie die Name-Eigenschaft. Diese wird als Name der Inhaltskomponente auf der Benutzeroberfläche von stsadm.exe, in der Zentraladministrationsanwendung und auf der Benutzeroberfläche aller benutzerdefinierten Sicherungs- und Wiederherstellungsanwendungen verwendet. In den meisten Fällen implementieren Sie die Eigenschaft, indem Sie ein privates Feld für den Namenswert erstellen und die öffentliche Eigenschaft als Wrapper für das Feld implementieren. Weitere Informationen zu möglichen Variantenimplementierungen finden Sie im Referenzthema zur Eigenschaft.
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
Wenn die Klasse nicht von SPPersistedObject abgeleitet wird, implementieren Sie die Id-Eigenschaft. In den meisten Fällen implementieren Sie die Eigenschaft, indem Sie ein privates Feld für den Namenswert erstellen und die öffentliche Eigenschaft als Wrapper für das Feld implementieren. Weitere Informationen zu möglichen Variantenimplementierungen finden Sie im Referenzthema zur Eigenschaft.
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
Implementieren Sie die DiskSizeRequired-Eigenschaft. Wenn die Klasse nur ein Container für untergeordnete IBackupRestore-Klassen ist, sollte von der Eigenschaft 0 zurückgegeben werden. Anderenfalls sollte von der Eigenschaft die Größe des Inhalts berechnet werden. Schließen Sie die Größe aller untergeordneten Nicht-IBackupRestore-Objekte ein, jedoch nicht die Größe untergeordneter IBackupRestore-Objekte. Diese Objekte haben jeweils eine eigene DiskSizeRequired-Eigenschaft, und diese Werte werden von SharePoint Foundation automatisch hinzugefügt.) Im folgenden Beispiel werden die Größen aller Dateien summiert, deren Pfade in einer Auflistung mit dem Namen FrontEndFilePaths enthalten sind.
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
Implementieren Sie die CanSelectForBackup-Eigenschaft. Wenn Benutzer nie in der Lage sein sollen, Objekte der Klasse unabhängig von einer Sicherung des übergeordneten Objekts zu sichern, sollte vom get-Accessor false zurückgegeben werden. Wenn Benutzer immer in der Lage sein sollen, ein beliebiges Objekt der Klasse für eine unabhängige Sicherung auszuwählen, sollte vom get-Accessor true zurückgegeben werden. In jedem Fall sollte der set-Accessor aus einem leeren Paar geschweifter Klammern ("{ }") bestehen. Wenn einige Objekte der Klasse unabhängig vom übergeordneten Objekt gesichert werden können, andere dagegen nicht, implementieren Sie die Eigenschaft als Wrapper für ein privates Boolean-Feld.
Implementieren Sie die CanSelectForRestore-Eigenschaft. Wenn Benutzer nie in der Lage sein sollen, Objekte der benutzerdefinierten Komponentenklasse unabhängig von einer Wiederherstellung des übergeordneten Objekts wiederherzustellen, sollte vom get-Accessor false zurückgegeben werden. Wenn Benutzer immer in der Lage sein sollen, ein beliebiges Objekt der Klasse für eine unabhängige Wiederherstellung auszuwählen, sollte vom get-Accessor true zurückgegeben werden. In jedem Fall sollte der set-Accessor aus einem leeren Paar geschweifter Klammern ("{ }") bestehen. Wenn einige Objekte der Klasse unabhängig vom übergeordneten Objekt wiederhergestellt werden können, andere dagegen nicht, implementieren Sie die Eigenschaft als Wrapper für ein privates Boolean-Feld.
Implementieren Sie die CanRenameOnRestore-Eigenschaft. Wenn Benutzer nie in der Lage sein sollen, Objekte der benutzerdefinierten Komponentenklasse an einem neuen Speicherort wiederherzustellen, sollte vom get-Accessor false zurückgegeben werden. Wenn Benutzer in der Lage sein sollen, beliebige Objekte der Klasse zu migrieren, sollte vom get-Accessor true zurückgegeben werden. Wenn Objekte der Klasse manchmal, aber nicht immer migriert werden können, implementieren Sie die Eigenschaft als Wrapper für ein privates Boolean-Feld.
Implementieren Sie die AddBackupObjects(SPBackupRestoreObject)-Methode.
Der Implementierungscode sollte immer mit dem Auslösen einer Ausnahme beginnen, wenn kein gültiges übergeordnetes Element vorhanden ist, dem die Komponente hinzugefügt werden kann.
Verwenden Sie die AddChild-Methode, um die Komponente der Objektstruktur hinzuzufügen, die beim Sicherungs- oder Wiederherstellungsvorgang verarbeitet werden soll.
Verwenden Sie die SetParameter(String, Object)-Methode, um einen Typnamen und eine Beschreibung der Komponente anzugeben, die von der Benutzeroberfläche von Sicherungs- und Wiederherstellungsanwendungen verwendet werden kann.
Wenn die Komponente untergeordnete IBackupRestore-Objekte hat, sollten diese von der Implementierung durchlaufen werden. Außerdem sollte die AddBackupObjects(SPBackupRestoreObject)-Methode der einzelnen untergeordneten Objekte rekursiv aufgerufen werden.
Weitere Informationen zur Implementierung dieser Methode finden Sie im Referenzthema zur AddBackupObjects(SPBackupRestoreObject)-Methode.
Im folgenden Codebeispiel wird angenommen, dass die Inhaltsklasse ein ChildContentCollection-Objekt aus untergeordneten IBackupRestore-Objekten hat. Wenn die Klasse mehrere untergeordnete Komponententypen hat, können Sie separate Auflistungen für die einzelnen Typen verwenden und die einzelnen Auflistungen durchlaufen.
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
Implementieren Sie die OnAbort(Object, SPBackupRestoreInformation)-Methode. Dadurch sollte immer true zurückgegeben werden. In den meisten Fällen sollte darüber hinaus nichts geschehen. Weitere Informationen zu Ausnahmen von dieser allgemeinen Regel finden Sie im Referenzthema zu OnAbort(Object, SPBackupRestoreInformation).
Implementieren Sie die OnPrepareBackup(Object, SPBackupInformation)-Methode. Sie sollten mindestens die SetParameter(String, Object)-Methode verwenden, um einen Namen für das Inhaltsobjekt anzugeben. Darüber hinaus können wenige Generalisierungen vorgenommen werden. Weitere Informationen finden Sie im Referenzthema zu OnPrepareBackup(Object, SPBackupInformation). Im folgenden Beispiel wird eine minimale Implementierung der Methode gezeigt, die in vielen Fällen ausreicht.
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
Implementieren Sie die OnBackup(Object, SPBackupInformation)-Methode. Wenn die Inhaltsklasse keine Inhalte außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekte enthält, sollte durch die Implementierung einfach CurrentProgress auf einen Wert festgelegt werden, der ungefähr den Prozentsatz der Gesamtdauer des Sicherungsvorgangs darstellt, der von den Methoden OnBackup(Object, SPBackupInformation) und OnPrepareBackup(Object, SPBackupInformation) beansprucht wird. Anschließend sollte wie im folgenden Beispiel true zurückgegeben werden. Rufen Sie nicht die OnBackup-Methode untergeordneter IBackupRestore-Objekte auf.
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
Wenn die Klasse Inhalte außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekte enthält, müssen diese Inhalte von der Implementierung nach args.Location kopiert werden. Wenn beim Kopieren Fehler auftreten, muss false zurückgegeben werden. Schließen Sie Logik zum Sichern aller untergeordneten Objekte ein, durch die nichtIBackupRestore implementiert wird. Sichern Sie jedoch nicht explizit untergeordnete Objekte, durch die IBackupRestore implementiert wird. Diese Objekte werden durch die eigene OnBackup(Object, SPBackupInformation)-Methode gesichert, die von der Laufzeit aufgerufen wird. Rufen Sie nicht die OnBackup(Object, SPBackupInformation)-Methoden der untergeordneten Objekte in Ihrem eigenen Code auf. Im folgenden Beispiel wird die allgemeine Struktur einer eigenständigen Implementierung von OnBackup(Object, SPBackupInformation) gezeigt:
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
Implementieren Sie die OnBackupComplete(Object, SPBackupInformation)-Methode. Von der Implementierung sollte mindestens wie im folgenden Beispiel gezeigt CurrentProgress auf 100 Prozent festgelegt und true zurückgegeben werden. Mehr ist normalerweise nicht erforderlich. Weitere Informationen zu anderen Aktionen, die möglicherweise von der Implementierung ausgeführt werden müssen, finden Sie im Referenzthema zu OnBackupComplete.
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
Implementieren Sie die OnPreRestore-Methode. In den meisten Situationen ist für einen Wiederherstellungsvorgang keine Vorbereitung erforderlich, und von der Implementierung von OnPreRestore sollte nur true zurückgegeben werden. Weitere Informationen zu anderen Aktionen, die möglicherweise von der Implementierung ausgeführt werden müssen, finden Sie im Referenzthema zu OnPreRestore.
Implementieren Sie die OnRestore-Methode.
Wenn die Inhaltsklasse migriert werden kann, sollte vom Code überprüft werden, welche Wiederherstellungsmethode verwendet wird. Wenn die New-Methode verwendet wird, sollte Rename() aufgerufen werden.
Wenn die Inhaltsklasse außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekt keine Inhalte enthält, sollte durch die Implementierung einfach CurrentProgress auf einen Wert festgelegt werden, der ungefähr den Prozentsatz der Gesamtdauer des Wiederherstellungsvorgangs darstellt, der von den Methoden OnRestore und OnPreRestore beansprucht wird. Dann sollte wie im folgenden Beispiel gezeigt true zurückgegeben werden. Rufen Sie nicht die OnRestore-Methode untergeordneter IBackupRestore-Objekte auf.
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
- Wenn die Klasse Inhalte außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekte enthält, müssen diese Inhalte durch die Implementierung in das Wiederherstellungsziel kopiert werden. Geben Sie false zurück, wenn beim Kopieren der Inhalte Fehler auftreten.
Im folgenden Beispiel wird die allgemeine Struktur einer eigenständigen Implementierung von OnRestore gezeigt:
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
Implementieren Sie die OnPostRestore-Methode. Von der Implementierung sollte mindestens wie im folgenden Beispiel gezeigt CurrentProgress auf 100 Prozent festgelegt und true zurückgegeben werden. Mehr ist normalerweise nicht erforderlich. Weitere Informationen zu anderen Aktionen, die möglicherweise von der Implementierung ausgeführt werden müssen, finden Sie im Referenzthema zu 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
Hinzufügen weiterer Member zur Klasse bei Bedarf
Fügen Sie nach Bedarf Felder, Eigenschaften und Hilfsmethoden hinzu, um die Klasse zu vervollständigen. Beachten Sie dabei Folgendes:
Verwenden Sie Felder und Eigenschaften, um darin untergeordnete Inhaltsobjekte zu speichern.
Wenn die Klasse von SPPersistedObject abgeleitet wird, muss der Deklaration der Felder, die dauerhaft in der Konfigurationsdatenbank gespeichert werden sollen, das [Persisted]-Attribut vorangestellt werden. Sie können jedoch nur die folgenden Feldtypen auf diese Weise kennzeichnen: einfache Typen wie beispielsweise Zeichenfolgen, Ganzzahlen und GUIDs, andere SPPersistedObject-Objekte oder SPAutoserializingObject-Objekte oder Auflistungen dieser Objekte. Die Klasse kann beispielsweise kein FileInfo-Feld haben, das mit dem [Persisted]-Attribut gekennzeichnet ist. Wenn die Daten, die dauerhaft gespeichert werden sollen, nicht zu einer dauerhaften Klasse gehören, verwenden Sie einen dauerhaften Ersatz. In der oben gezeigten Beispielimplementierung der DiskSizeRequired-Eigenschaft wird eine Klasse verwendet, von der eine Auflistung von Dateinamen dauerhaft gespeichert und zur Laufzeit zum Erstellen einer temporären Auflistung von FileInfo-Objekten verwendet wird.
Wenn die Klasse mehrere untergeordnete Klassen des gleichen Typs haben kann, erstellen Sie eine Eigenschaft oder ein Feld eines Auflistungstyps oder eines anderen aufzählbaren Typs, um darin eine Auflistung aller untergeordneten Klassen eines bestimmten Typs zu speichern. Dies ist besonders wichtig, wenn vom untergeordneten Typ selbst IBackupRestore implementiert wird. Der Grund ist, dass von der Implementierung der AddBackupObjects(SPBackupRestoreObject)-Methode solche untergeordneten Klassen durchlaufen werden und die AddBackupObjects(SPBackupRestoreObject)-Methoden der einzelnen untergeordneten Klassen aufgerufen werden sollten. Weitere Informationen finden Sie weiter oben im Verfahrensschritt für das Implementieren der AddBackupObjects(SPBackupRestoreObject)-Methode.
Fügen Sie der Klasse Konstruktoren hinzu, um die Felder und Eigenschaften der Klasse nach Bedarf zu initialisieren. Wenn die Klasse von SPPersistedObject abgeleitet wird, muss mindestens ein Konstruktor vorhanden sein, von dem das Objekt benannt und einem übergeordneten Objekt zugewiesen wird. Normalerweise werden für einen solchen Konstruktor mindestens diese beiden Argumente verwendet:
Ein String-Argument, das dem Namen des Inhaltsobjekts entspricht.
Ein SPPersistedObject-Argument, das das übergeordnete Objekt des Inhaltsobjekts darstellt.
Von diesem Konstruktor muss der Basiskonstruktor aufgerufen werden, für den die gleichen zwei Argumente verwendet werden können. Der folgende Code ist ein Beispiel dafür.
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
Sie müssen SPFarm.Local als übergeordnetes Objekt übergeben, wenn das Inhaltsobjekt das oberste Objekt in einer Struktur aus benutzerdefinierten IBackupRestore-Objekten ist. Wenn der benutzerdefinierte Komponententyp immer das oberste Objekt ist, lassen Sie das SPPersistedObject-Argument weg, und codieren Sie im Aufruf des Basiskonstruktors einen festen Verweis auf SPFarm.Local. Der folgende Code ist ein Beispiel dafür:
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
Wenn Objekte der Klasse immer den gleichen Namen haben, können Sie das String-Argument weglassen und den Namen im Aufruf des Basiskonstruktors fest codieren. (Wenn alle Objekte eines bestimmten Typs den gleichen Namen haben, sollte für ein bestimmtes übergeordnetes Objekt nie mehr als ein untergeordnetes Objekt dieses Typs vorhanden sein. Entsprechend sollte in der gesamten Farm nie mehr als ein Objekt dieses Typ vorhanden sein, wenn das Objekt ein untergeordnetes Objekt der Farm ist.)
Kompilieren Sie das Klassenprojekt.
Vorsicht Geben Sie der Assembly einen starken Namen, und platzieren Sie die Assembly im globalen Assemblycache (Global Assembly Cache, GAC).
So erstellen Sie ein Objekt der Klasse und legen dieses als untergeordnetes Objekt der Farm fest
Starten Sie ein neues Konsolenanwendungsprojekt in Visual Studio.
Fügen Sie dem Projekt einen Verweis auf die DLL der benutzerdefinierten Komponentenklasse hinzu.
Fügen Sie eine using-Anweisung für Microsoft.SharePoint.Administration hinzu.
Fügen Sie eine using-Anweisung für den Namespace hinzu, den Sie in der benutzerdefinierten Komponentenklasse verwendet haben (oder verwenden Sie einfach in der Konsolenanwendung den gleichen Namespace).
Fügen Sie der Main-Methode des Projekts einen Aufruf des Konstruktors der benutzerdefinierten Komponentenklasse hinzu. Wenn Sie eine Hierarchie aus benutzerdefinierten Typen erstellt haben, rufen Sie den Konstruktor der obersten Klasse auf.
Stellen Sie bei Bedarf dem Aufruf des Konstruktors der Komponente Code voran, mit dem Parameter für den Konstruktor erstellt werden.
Nach dem Aufruf des Konstruktors der Komponente sollte die Update-Methode des Komponentenobjekts aufgerufen werden. Im folgenden Beispiel wird gezeigt, was in der Main-Methode enthalten sein sollte:
MyContentComponent myContentObject = new MyContentComponent("component name", SPFarm.Local); myContentObject.Update();
Dim myContentObject As New MyContentComponent("component name", SPFarm.Local) myContentObject.Update()
Kompilieren Sie die Anwendung, und führen Sie sie aus.
Navigieren Sie in der Zentraladministrationsanwendung zu Vorgänge | Sicherung durchführen. Das Objekt sollte auf der Seite Sicherung ausführen als untergeordnetes Objekt der Farm angezeigt werden.
Hinweis Im Abschnitt Beispiel weiter unten finden Sie ein Beispiel für eine Konsolenanwendung zum Erstellen und Löschen benutzerdefinierter Inhaltsobjekte.
Ratschläge für die Entwicklung
Die folgenden Tipps können beim Entwickeln benutzerdefinierter Inhaltsklassen hilfreich sein, insbesondere da Sie dabei wahrscheinlich mehrfach Objekte erstellen und der Farm hinzufügen.
Zu berücksichtigende Punkte
Wenn Sie das Objekt aus der Konfigurationsdatenbank löschen möchten, verwenden Sie Delete().
Wenn Sie obj.Update() aufrufen und bereits ein Objekt der gleichen Klasse als obj mit dem gleichen Name-Eigenschaftswert und dem gleichen übergeordneten Objekt in der Konfigurationsdatenbank vorhanden ist, wird eine Ausnahme ausgelöst. Es gibt eine überladene Version von Update, die möglicherweise besser geeignet ist.
Im zweiten Abschnitt Beispiel weiter unten finden Sie ein Beispiel für eine Konsolenanwendung, mit der benutzerdefinierte Objekte in der Konfigurationsdatenbank hinzugefügt oder gelöscht werden können.
Führen Sie nach jeder erneuten Kompilierung der IBackupRestore-Klasse iisreset auf der Befehlszeile aus. Möglicherweise müssen Sie auch den Server neu starten.
Für die verschiedenen IBackupRestore.On*-Methoden kann ein SPBackupInformation-Parameter oder ein SPRestoreInformation-Parameter verwendet werden. Sie können die Member der Methoden zu Debuggingzwecken verwenden. Besonders hilfreich ist die LogLog-Methode.
Beispiel
Im folgenden Code wird eine benutzerdefinierte Komponente implementiert, die eine einzelne Datei Web.config auf einem Front-End-Server darstellt. Ersetzen Sie TestSite im Dateipfad in der Konstruktorimplementierung durch einen Verzeichnisnamen auf dem Testserver. Die kompilierte Assembly muss einen starken Namen haben und im GAC installiert sein.
Das Beispiel nach der Klassenimplementierung enthält Code für eine einfache Konsolenanwendung, mit der die Komponente als untergeordnete Komponente der Farm registriert oder aus der Farm gelöscht wird.
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
Mit der folgenden Konsolenanwendung wird das Inhaltsobjekt in der Konfigurationsdatenbank hinzugefügt oder gelöscht.
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
Siehe auch
Aufgaben
Gewusst wie: Programmgesteuertes Sichern von Inhalten
Gewusst wie: Programmgesteuertes Wiederherstellen von Inhalten
Gewusst wie: Programmgesteuerte Sicherung und Wiederherstellung einer einzelnen Websitesammlung
Gewusst wie: Erstellen einer Datenbankklasse, die aus einem Snapshot wiederhergestellt werden kann
Referenz
Microsoft.SharePoint.Administration.Backup
Konzepte
Programmieren mit dem Sicherungs-/Wiederherstellungsobjektmodell von SharePoint Foundation