Klassen zu Datenbank-Skript

30. Juli 2010

Das Entity Framework von Microsoft bietet gute Möglichkeiten für die Modellierung von Daten-Entitäten. In den Diagrammen lassen sich die Beziehungen der Entitäten untereinander und die Attribute definieren und wenn das geschafft ist, lassen sich aus diesen Meta-Daten Datenbank-Tabellen und entsprechende Zugriffsklassen generieren.

Das Entity-Framework setzt aber ein manuell erstelltes Model – eine XML-Struktur, welche die Entitäten detailliert beschreibt – oder eine fertige Datenbank voraus, um mit der Generierung der Zugriffs-Klassen beginnen zu können. Die Generierung des Model aus einer Datenbank wird unterstützt – die Generierung aus bereits existierenden .Net-Klassen aber nicht. Damit ergibt sich in einigen Fällen, der unschöne Zustand, dass die Business-Klassen schon fertig modelliert sind, aber dann die Erstellung der Datenbank-Schemas oder des Models wieder getrennt davon per Hand durchgeführt werden muss. Eine Generierung der Datenbank-Tabellen mit allen Referenzen sollte aus .Net Klassen doch auch recht einfach gelingen.

Ich höre schon Matthias sagen „wozu etwas in 2h einfach machen, wenn man auch 2 Tage daran programmieren kann“ … ich habe es trotzdem gemacht: ich habe mit nach einiger erfolgloser Google-Recherche einen Klassen-zu-Datenbank-Konverter geschrieben (siehe statische Klasse DatabaseScriptGenerator im Projekt Sem.GenericHelpers auf http://semsync.codeplex.com/). Ich habe es zugegebenermaßen bisher nur mit meinem Klassenmodell ausprobiert (dem entsprechend wenige Typen-Übersetzungen sind bisher auch drin), aber es klappt zumindest prinzipiell auch mit generischen Listen von „irgendwas“ und Enums. Die Primary- und Foreign-Keys werden ebenfalls mit angelegt.

Um die Funktionalität zu nutzen, muss zunächst die Solution von CodePlex heruntergeladen werden. Die Klassen sind im Projekt Sem.GenericHelpers, welches noch ExpressionSerialization referenziert. Diese beiden Projekte (oder die erstellten Assemblies) müssen also in die eigene Solution mit eingebunden werden.

Der Aufruf gestaltet sich im eigenen Projekt sich recht übersichtlich:

using Sem.GenericHelpers.Database;
...
var result = DatabaseScriptGenerator.CreateScriptFromEntityType(
    typeof(StdContact), 
    "Contacts");
...

Die Methode erwartet den Typen der Haupt-Entität (von der ausgehend die Tabellen generiert werden) und einen Namen für die dazugehörige Tabelle. Zurück kommt ein String mit dem Datenbank-Script:

CREATE TABLE Contacts (
[ContactsId] int NOT NULL IDENTITY (1, 1),
[AdditionalTextData] nvarchar(255),
[BusinessAddressPrimaryRef] INT,
[BusinessAddressSecondaryRef] INT,...

Es wird in jeder Entitäten-Tabelle eine Identity-Spalte mit dem Namen der Tabelle und dem Suffix „Id“ angelegt; Verweise auf Tabellen für Sub-Entitäten erhalten das Suffix „Ref“. Die Klassen werden rekursiv von einer „Haupt-Entität“ ausgehend aufgebaut.

Es ist nicht das ultimative Tool, um ein komplexes Datenbank-Schema zu erstellen und das erstellte Schema bedarf mit Sicherheit noch einiges an „Nacharbeit“ – aber man kann damit zumindest schon mal was in der Datenbank sehen. Das Projekt, in dem diese Funktionalität entstanden ist, steht unter LGPL – die Bibliotheken können also problemlos in freien oder auch kommerziellen Projekten eingesetzt werden.