EDM: Code First - Datenbank erweitern

Wenn Sie ein Abonnement des Magazins 'DATENBANKENTWICKLER' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Das ListView-Steuerelement

Im Artikel »EDM: Der Code First-Ansatz« haben wir uns angesehen, wie Sie auf Basis eines frisch erstellten Entity Data Models eine Datenbank samt den nötigen Tabellen erstellen können – und zwar automatisch beim ersten Zugriff auf die noch nicht vorhandene Datenbank. Nun gehen wir einen Schritt weiter und zeigen, wie Sie auch noch Änderungen am Entity Data Model auf bestehende Datenbanken mit älterem Versionsstand übertragen und somit ein kombiniertes Update von Anwendung und Datenbank ausliefern können.

Aktualisierungen am bestehenden Datenmodell

Wir haben während der Entwicklung der Anwendung, wie wir es im Artikel EDM: Der Code First-Ansatz gelernt haben, die Freiheit, nach Lust und Laune die Zieldatenbank zu löschen und neu zu erstellen. Wohlgemerkt: während der Entwicklung! Sobald die Datenbank jedoch einmal mit Daten gefüllt ist oder sogar beim Kunden läuft, wollen Sie Aktualisierungen am Datenmodell sicher etwas eleganter und ohne Datenverlust übermitteln. Auch dazu bietet Code First Möglichkeiten.

Um Migrationen mit Code First durchzuführen, also die Änderungen erst am bestehenden Modell der Entitäten durchzuführen und diese dann auf die Tabellen der Datenbank zu übertragen, müssen wir zunächst die Migrationsfunktion aktivieren.

Dazu benötigen wir die Paket-Manager-Konsole, die Sie mit dem Menübefehl Ansicht|Weitere Fenster|Paket-Manager-Konsole einblenden. Ist dieser eingeblendet, wählen Sie oben rechts unter Standardprojekte den Namen des betroffenen Projekts aus, in diesem Fall CodeFirst. Dann geben Sie den folgenden Befehl ein:

PK> enable-migrations

Das Ergebnis finden Sie in Bild 1 vor.

Aktivieren der Migrationsfunktion

Bild 1: Aktivieren der Migrationsfunktion

Im Projekt haben sich nun einige Änderungen ergeben, die Sie direkt im Projektmappen-Explorer ablesen können. Dort finden Sie nun nämlich einen neuen Ordner namens Migrations (siehe Bild 2). Dieser enthält eine Datei namens Configuration.vb.

Die neue Konfigurationsdatei

Bild 2: Die neue Konfigurationsdatei

Diese Datei enthält vor allem die Seed-Methode. Dieser können Sie Anweisungen zum Schreiben von Daten in die Tabellen der Datenbank hinzufügen. Die Seed-Methode wird später beim Update des Datenbank-Backends ausgelöst. Deshalb fügen wir beispielsweise die folgenden Codezeilen zu dieser Methode in der Klasse Configuration.vb hinzu:

Namespace Migrations
     Friend NotInheritable Class Configuration 
         Inherits DbMigrationsConfiguration(Of Wordgenerator)
         Public Sub New()
             AutomaticMigrationsEnabled = False
             ContextKey = "CodeFirst.Wordgenerator"
         End Sub
         Protected Overrides Sub Seed(context As Wordgenerator)
             Dim anrede As New Anrede With {.Bezeichnung = "Herr"}
             context.Anreden.AddOrUpdate(Function(p) p.Bezeichnung, anrede)
             anrede = New Anrede With {.Bezeichnung = "Frau"}
             context.Anreden.AddOrUpdate(Function(p) p.Bezeichnung, anrede)
             anrede = New Anrede With {.Bezeichnung = "Firma"}
             context.Anreden.AddOrUpdate(Function(p) p.Bezeichnung, anrede)
         End Sub
     End Class
End Namespace

Damit wollen wir sicherstellen, dass zumindest die grundlegenden Daten der Anwendung, nämlich die Anreden, bereits in die Tabelle Anreden geschrieben werden – hier also die Datensätze mit den Werten Herr, Frau und Firma im Feld Bezeichnung.

Anschließend geben Sie einen weiteren Befehl in den Bereich Paket-Manager-Konsole ein (siehe Bild 3):

Initiale Migration

Bild 3: Initiale Migration

PM> Add-Migration Initial

Dadurch wird eine weitere Datei zum Ordner Migrations hinzugefügt, diesmal nach dem Schema 201802121707380_Initial.vb. Diese Klasse enthält eine Methode namens Up, die drei CreateTable-Anweisungen enthält, mit denen die Tabellen entsprechend der Entitäten Anrede, Adresse und Brief erstellt werden – hier in gekürzter Form nur mit den Anweisungen für die Tabelle Anreden:

Public Overrides Sub Up()
     ...
     CreateTable(
         "dbo.Anreden",
         Function(c) New With
             {
                 .ID = c.Int(nullable := False, identity := True),
                 .Bezeichnung = c.String()
             }) _
         .PrimaryKey(Function(t) t.ID)
     ...
End Sub

Zusätzlich enthält die Klasse noch eine Methode namens Down, welche die bestehenden Schlüssel, Indizes und Tabellen löscht:

Public Overrides Sub Down()
     DropForeignKey("dbo.Briefe", "Adresse_ID", "dbo.Adressen")
     DropForeignKey("dbo.Adressen", "Anrede_ID", "dbo.Anreden")
     DropIndex("dbo.Briefe", New String() { "Adresse_ID" })
     DropIndex("dbo.Adressen", New String() { "Anrede_ID" })
     DropTable("dbo.Briefe")
     DropTable("dbo.Anreden")
     DropTable("dbo.Adressen")
End Sub

Außerdem setzen Sie im gleichen Bereich noch den folgenden Befehl ab:

PM> Update-Database

Damit rufen Sie zunächst die Methoden der Klasse 201802121707380_Initial.vb auf, welche die Datenbank und das Datenmodell anlegt, wenn diese noch nicht vorhanden ist, und dann mit der Seed-Methode die initialen Daten in die Tabelle Anreden schreibt.

Änderungen am Datenmodell

Nun nehmen wir eine kleine Änderung am Datenmodell vor. Wohlgemerkt: Die aktuelle Version, die durch die Datei 201802121707380_Initial.vb beschrieben wird, haben wir durch die Update-Database-Methode in der Paket-Manager-Konsole bereits angewendet und damit eine neue Datenbank erzeugt. Nun fügen wir der Entität Anreden eine Eigenschaft namens Briefanrede hinzu:

<Table("Anreden")>
Public Class Anrede
     Public Property ID As Integer
     Public Property Bezeichnung As String

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.