Dies ist der siebte Teil einer Serie, die sich mit der Frage beschäftigt auf welche Arten Konfigurationen in Applikationen unter SharePoint gespeichert werden können. Es wird zuerst immer kurz die Methode vorgestellt, gefolgt von einem kurzen Beispiel und den Vor- und Nachteilen.
Eine vollständige Übersicht über bisherige und noch folgende Artikel ist hier zu finden.
Im heutigen Teil wird eine Möglichkeit vorgestellt auf Daten zuzugreifen ohne in der Applikation Kenntnisse über das Quellsystem zu besitzen.
Zu den vielfältigen Services, welche SharePoint anbietet, gehört der Nachfolger des Business Data Catalog (BDC) die Business Data Connectivity Services (BCS). Diese dienen dazu beliebige Fremdsysteme an SharePoint anzubinden und ermöglichen Daten aus Datenbanken, Web Services oder auch SAP in SharePoint verfügbar zu machen. Die BCS sind also weniger dazu geeignet z.B. einen ConnectionString zu speichern. Dafür aber umso besser um Daten direkt aus Fremdsystemen auszulesen.
Im Rahmen dieser Serie werden die Business Data Connectivity Services als einfacher Zugriff auf eine Konfigurationsdatenbank verwendet. Das bedeutet, wir legen eine für uns passende Entität in SharePoint an und konfigurieren diese für den Zugriff auf unsere Datenbank. Eine Applikation muss sich dann nicht mehr um die Verbindung kümmern. Es wird „nur“ die Entität angefragt und aus Sicht der Applikation stammen die Daten immer aus SharePoint.
Das hier aufgeführte Beispiel kann aber natürlich auch verwendet werden um unserer Applikation Daten aus einem beliebigen Fremdsystem zur Verfügung zu stellen.
BDC Model erstellen
Das Bindeglied zwischen SharePoint und Fremdsystemen sind die so genannten External Content Types. Es gibt zwei Möglichkeiten diese zu erstellen:
- Anlegen des Modells in Visual Studio.
- Modell mit SharePoint Designer erstellen.
Da die zweite Variante einfacher ist, gehen wir für unser Beispiel diesen Weg.
Zuerst erstellen wir eine Tabelle, auf welche wir dann später zugreifen wollen:
CREATE TABLE [dbo].[Konfiguration](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Kategorie] [varchar](50) NOT NULL,
[Name] [varchar](50) NOT NULL,
[Wert] [varchar](50) NULL
) ON [PRIMARY]
Als nächstes starten wir den SharePoint Designer und öffnen unsere Site:
Hier wählen wir „External Content Types“ (ECT) und klicken auf “New”:
Wir geben dem ECT einen Namen und wählen „External System“ um die Datenquelle zu definieren:
Im folgenden Dialog fügen wir eine neue Verbindung mit „Add Connection“ hinzu:
In dem aufgehendem Dialog wählen wir den passenden SQL-Server und konfigurieren die Verbindung zu unserer Datenbank. Die Verbindung kann auch über dem im letzten Teil vorgestellten Secure Store erfolgen. Dazu muss im Dialog nur der Name des Secure Stores angegeben werden. Dieser benötigt natürlich das Recht den Secure Store auszulesen:
Nach Klick auf “Ok”, legt der SharePoint Designer die Verbindung im Metadata Store an. Wir wählen nun unsere Konfigurationstabelle mit einem Rechtsklick aus, und wählen „Create All Operations“:
Dies startet einen Wizard in dem wir auf „Next“ klicken:
Im nächsten Fenster müssen wir eine eindeutige Id Spalte benennen. Ohne diese kann SharePoint nicht mit den Daten arbeiten:
Im letzten Dialogfenster können wir noch einen Filter definieren. Dieser ist für unser Beispiel jedoch unerheblich. Wir beenden also den Wizard mit Klick auf „Finish“:
Der SharePoint Designer erstellt nun alle CRUD Operationen:
Zum Abschluss wird der External Content Type gespeichert und die Definition im Metadata Store abgelegt. In der Central Administration sind diese unter “Application Management” -> “Manage service applications” -> “Business Data Connectivity Service” zu finden.
Zugriff auf BCS
Zum Arbeiten mit den BCS benötigen wir zuerst einmal ein einfaches Datenobjekt:
public class Konfiguration
{
public int Id { get; set; }
public string Name { get; set; }
public string Kategorie { get; set; }
public string Wert { get; set; }
}
Als nächstes benötigen wir ein Repository, mit dem Einträge aus der Tabelle ausgelesen und geändert werden können. Dieses kommuniziert mit den BCS:
[DataObject]
public class KonfigurationRepository
{
private const string LobInstanceName = "Datenbank Beispiel";
private const string EntityName = "BeispielECT";
private const string EntityNameSpace = "http://spdev/personal/markus";
[DataObjectMethod(DataObjectMethodType.Select, true)]
public List<Konfiguration> Select()
{
var list = new List<Konfiguration>();
using (new SPServiceContextScope(SPServiceContext.GetContext(SPContext.Current.Site)))
{
// BCS Service ansprechen
var service = SPFarm.Local.Services.GetValue<BdcService>();
// Metadata Store für BCS Service ermitteln
var catalog = service.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current);
// External Content Type definieren
var entity = catalog.GetEntity(EntityNameSpace, EntityName);
// LOB System laden
var instances = entity.GetLobSystem().GetLobSystemInstances();
var lobSysteminstance = instances[LobInstanceName];
// Read Methode definieren
var method = entity.GetMethodInstance("Read List", MethodInstanceType.Finder);
// Items abfragen
var items = entity.FindFiltered(method.GetFilters(), lobSysteminstance);
while (items.MoveNext())
{
if (items.Current != null)
{
// BCS Objekt auf Datenobjekt mappen
list.Add(new Konfiguration()
{
Id = (int)items.Current["Id"],
Name = items.Current["Name"].ToString(),
Kategorie = items.Current["Kategorie"].ToString(),
Wert = items.Current["Wert"].ToString()
});
}
}
}
return list;
}
[DataObjectMethod(DataObjectMethodType.Update, true)]
public void Update(Konfiguration neueKonfig)
{
using (new SPServiceContextScope(SPServiceContext.GetContext(SPContext.Current.Site)))
{
// BCS Service ansprechen
var service = SPFarm.Local.Services.GetValue<BdcService>();
// Metadata Store für BCS Service ermitteln
var catalog = service.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current);
// External Content Type definieren
var entity = catalog.GetEntity(EntityNameSpace, EntityName);
// LOB System laden
var instances = entity.GetLobSystem().GetLobSystemInstances();
var lobSysteminstance = instances[LobInstanceName];
// Id für Abfrage definieren
var identity = new Identity(neueKonfig.Id);
// Objekt laden, Werte setzen und updaten.
var instance = entity.FindSpecific(identity, lobSysteminstance);
instance["Name"] = neueKonfig.Name;
instance["Wert"] = neueKonfig.Wert;
instance.Update();
}
}
}
Als letztes erstellen wir ein WebPart mit einem GridView und einer ObjectDataSource um die Daten anzeigen und bearbeiten zu können:
public class WebPartMitBCS : WebPart
{
protected override void CreateChildControls()
{
var dataSource = new ObjectDataSource
{
ID = "Source",
UpdateMethod = "Update",
SelectMethod = "Select",
TypeName = typeof(KonfigurationRepository).AssemblyQualifiedName,
DataObjectTypeName = typeof(Konfiguration).AssemblyQualifiedName
};
var gridView = new GridView
{
ID = "GridViewKonfig",
AutoGenerateEditButton = true,
AutoGenerateColumns = true,
DataSourceID = dataSource.ID
};
Controls.Add(dataSource);
Controls.Add(gridView);
// DataBind wird sonst mehrfach aufgerufen
if (!Page.IsPostBack)
{
gridView.DataBind();
}
}
}
Fazit
Zum Abschluss wieder die Vor- und Nachteile der Business Data Connectivity Services:
Vorteile:
- Sicherheit
Rechte können sehr granular in SharePoint verwaltet werden.
- Scope
Es können beliebige Datenquellen angebunden werden. SharePoint kümmert sich hierbei um den Datenzugriff
Nachteile:
- Administration
Es gibt keine mitgelieferte Oberfläche zum Verwalten der Werte.
- Implementierung
Umsetzung ist sehr aufwendig im Vergleich zu anderen Methoden.
- Wartbarkeit
External Content Types müssen separat erstellt und verteilt werden