Daten unter SharePoint speichern – SPPersistedObject
avatar

Wenn es um das Speichern benutzerdefinierten Daten unter SharePoint geht gibt es ja bekanntlich mehrere Möglichkeiten (eine kleine Übersicht findet sich hier) die je nach Verwendungszweck alle ihre Vor- und Nachteile haben.

Eine Möglichkeit die einen guten Kompromiss zwischen Performance und Flexibilität ermöglicht ist die Speicherung von Daten anhand von SPPersistedObject Objekten.

Vorteile des SPPersistedObject:

Hier noch ein paar weitere Fakten dieser Klasse:

  • Namespace der Klasse: Microsoft.SharePoint.Administration
  • Die Klasse dient als Basisklasse für viele SP-Objekte, gerade im Administration-Bereich
  • Daten werden als XML-BLOB in der Datenbank gespeichert
  • Die Klasse wird zur Realisierung des sogenannten „Hierarchical Object Store“ verwendet
  • Die Klasse bietet einen persistenten SPPropertyBag, einen Hashtable zur indexierten Ablage
  • Die Objekte stehen allen Services der Farm zur Verfügung, unabhängig vom Parent-Objekt

Grundlegende Deklaration

using System;
using Microsoft.SharePoint.Administration;

namespace Impuls.SharePoint.Extensions.WebTracking.Config
{
    public class DataObject : SPPersistedObject
    {
        [Persisted]
        public string data = string.Empty;

        public DataObject()
        {           
        }

        public DataObject(string name, SPPersistedObject parent, Guid id)
            : base(name, parent, id)
        {            
        }

        public DataObject(string name, SPPersistedObject parent)
            : base(name, parent)
        {            
        }       
    }
}

Wobei es in diesem Fall wichtig ist einen der parametrisierten Konstruktoren inklusive base-Aufruf als auch den parameterlosen Konstruktor zu definieren, da dieser bei der Deserialisierung des Objekts verwendet wird.
Es existiert ein Konstruktor für den Fall das man die ID des Objektes nicht selbst bestimmen möchte. In diesem Fall wird automatisch eine neue GUID für das Objekt erstellt, die im Nachhinein natürlich noch abgefragt werden kann.

Das Persisted-Attribut

Der Kernpunkt der obigen Deklaration ist das Persisted-Attribut welches verwendet wird um persistente, also dauerhaft in der Datenbank zu speichernde Daten zu kennzeichnen.
Bezüglich des Attributs gibt es zwei Dinge zu beachten:

  • Es kann nur auf öffentliche Felder angewandt werden, keine Eigenschaften
  • Es kann nur für primitive Typen verwendet werden, also für string, int, GUID, Hashtable, Enumerationen etc.

Es kann für (generische) Listen von primitiven Typen verwendet werden

Wenn kein öffentliches Feld der Klasse mit diesem Attribut ausgestattet ist wird nur der PropertyBag dauerhaft gespeichert. Desweiteren können auch andere SPPersistedObject-Objekte (und Listen davon) die als Felder der Klasse fungieren mit diesem Attribut ausgestattet werden um sie automatisch mitzuspeichern.

Falls man, was durchaus mal schnell passieren kann, den Hierarchical Object Store einmal korrumpiert hat, indem man einen komplexen Typ verwendet hat oder ähnliches, hilft dieser Artikel weiter: Repairing the Hierarchical Object Store

Initialisierung und Verwendung

Die Verwendung der Klasse gestaltet sich relativ simpel.

WICHTIGER HINWEIS
Für das Ausführen der Update(), Delete() und Unprovision() Methoden muss der Code im Kontext eines Users sein, der sowohl Farm-Administrator ist als auch Zugriff auf die SharePoint_Conf-Datenbank hat. Wenn der Code innerhalb der Central Administration von SharePoint läuft, oder innerhalb einer Content-WebApplication die den selben Service- bzw. ApplicationPool-Account wie die CA hat, genügt es den Code innerhalb einer RunWithElevatedPrivileges-Anweisung auszuführen, da es sonst zu SQL- oder SecurityExceptions kommt!

//Eigenschaften des Objekts
SPWebApplication parent = SPContext.Current.Site.WebApplication;
Guid id = new Guid("2BF59217-A6D4-4333-8DB9-27BBC6313E18");
string name = "MyDataObject";

//Initialisierung
DataObject dataObj = new DataObject(name, parent, id);

//Zuweisung von Werten
dataObj.data = "foo";
//Zuweisung von Werten im PropertyBag
dataObj.Properties.Add("MyKey", "bar");

//Speichern der Werte
dataObj.Update();

//Löschen des Objekts
dataObj.Delete();
dataObj.Unprovision();

Wichtig ist hierbei die Zuweisung des Parent-Objekts und die Verwendung der dedizierten Methoden zum Speichern von Werten in der Datenbank und Löschen des gesamten Objekts aus der Datenbank.
Als Parent-Objekte kommen sämtliche von SPPersistedObject abgeleiteten Klassen in Frage, zu denen der Großteil der im Namespace Microsoft.SharePoint.Administration definierten Klassen gehören.

Das Abrufen des gespeicherten Objektes gestaltet sich ähnlich einfach und kann auf zwei Arten geschehen:

//Allgemeines Abrufen über ein SPFarm-Objekt
SPFarm farm = SPFarm.Local;
DataObject dataObj = (DataObject)farm.GetObject(new Guid("2BF59217-A6D4-4333-8DB9-27BBC6313E18"));

//Kontextnahes Abrufen über das Parent-Objekt
SPWebApplication parent = SPContext.Current.Site.WebApplication;
DataObject dataObj = parent.GetChild<DataObject>(name);

Fazit

Das SPPersistedObject bzw. dessen abgeleitete Klassen eignen sich hervorragend um hierarchisch orientierte Daten im SharePoint eigenen „Hierarchical Object Store“ dauerhaft zu Speichern und bequem zu verwenden. Durch ihre farmweite Verfügbarkeit eignen sich die Klassen sehr gut für die Implementierung eigener Erweiterungen und vor allem deren Einstellungsdaten.

Es sollte aber beachtet werden das dieser Ansatz je nach Verwendungszweck nicht unbedingt der beste ist, und z.B. die SPPropertyBag-Eigenschaften der SPWeb-, SPFolder– und SPListItem-Objekte eventuell ausreichen und sich vor allem aus Performance-Sicht besser eignen wenn es um größere Datenmengen geht (Performancevergleich „Hierarchical Object Store vs. PropertyBag“).

Schreibe einen Kommentar