Ausblick auf die kommende Version 4.5

Neues Jahr neues Entity Framework (Teil 3)
Kommentare

Automatisches Migrieren von Datenbanken bei Code Only
Bis dato war das Entity Framework bei der Verwendung von Code Only (siehe Kasten „Code Only“) nicht in der Lage, das Datenbankschema anhand der an

Automatisches Migrieren von Datenbanken bei Code Only

Bis dato war das Entity Framework bei der Verwendung von Code Only (siehe Kasten „Code Only“) nicht in der Lage, das Datenbankschema anhand der an den Entitätsklassen durchgeführten Änderungen zu aktualisieren. Die Komponente Migrations, die als Betaversion vorliegt und über NuGet [2] bezogen werden kann, ändert dies nun (Abb. 6).

Abb. 6: Migrations via NuGet installieren
Abb. 6: Migrations via NuGet installieren

Nach dem Einbinden von Migrations steht im Ordner Migrations eine Klasse Configuration zur Verfügung. Diese erbt von DbMigrationsConfiguration, wobei der Typparameter T auf den heranzuziehenden DbContext zu fixieren ist. Die Methode Seed wird im Zuge jeder Migration aufgerufen und kann zum Anlegen von vorgegebenen Datensätzen herangezogen werden (Listing 9).

Listing 9

namespace HotelSample.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : 
                       DbMigrationsConfiguration< HotelContext >
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        
        }

        protected override void Seed(HotelContext context)
        {
            base.Seed(context);
        }
    }
}
  

Code Only

Seit einigen Monaten steht mit Code Only ein weiteres Programmiermodell für das Entity Framework zur Verfügung. Es kommt ohne explizites Entity Data Model aus. Stattdessen stellt der Entwickler Entitätsklassen als herkömmliche .NET-Klassen und eine Ableitung von DbContext als leichtgewichtige Alternative zum ObjectContext zur Verfügung. Das Entity Framework bildet die Entitäten unter Berücksichtigung vorgegebener Konventionen auf ein Datenbankschema ab. Diese Konventionen legen unter anderem fest, dass Primärschlüssel entweder auf Id oder auf Klassenname + Id zu lauten haben. Möchte man aus diesem vorgegebenen Regelwerk ausbrechen, kann dies durch den Einsatz von Attributen oder durch Überschreiben von OnModelCreating im DbContext bewerkstelligt werden. Um in den Genuss dieses Programmiermodells zu kommen, ist die Bibliothek EntityFramework via NuGet zu beziehen.

Ein Beispiel für die Verwendung von Code Only zeigt Listing 10, ausführlichere Informationen über die verschiedenen Möglichkeiten von Code Only sind in Ausgabe 3.2011 des dot.NET Magazins zu finden.

Listing 10

[Table("Regionen")]
public class Region
{
    public Region()
    {
        Hotels = new List();
    }
    public int RegionId { get; set; }

    [MaxLength(30)]
    [Required]
    [Column("Bez")]
    public string Bezeichnung { get; set; }

    public string Land { get; set; }

    public string IntBezeichnung { get; set; }

    public virtual ICollection Hotels { get; set; }

    [ConcurrencyCheck]
    public int Version { get; set; }
}

public class Hotel
{
    [Key]
    public int HotelCode { get; set; }
    public string Bezeichnung { get; set; }
    public int Sterne { get; set; }
    public virtual Region Region { get; set; }
    public string Telefonnummer { get; set; }
    public int RegionId { get; set; }
}
public class WellnessHotel : Hotel
{
    public int AnzahlSaunen { get; set; }
    public int AnzahlPools { get; set; }
}
public class HotelContext : DbContext
{
    public HotelContext() : base("HotelDb-CodeFirst") { }

    public DbSet Hotels { get; set; }
    public DbSet Regionen { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove();

        // Die Standard-Konvention, die besagt, 
        // dass für Tabellennamen der Pluarl der 
        // jeweiligen Klassennamen herangezogen 
        // werden soll, entfernen. 
        modelBuilder.Conventions.Remove();

        // Table per Type-Vererbungsmapping 
        modelBuilder.Entity().ToTable("Hotels");
        modelBuilder.Entity().ToTable("WellnessHotels");
    }
}
  

Innerhalb des Konstruktors wird mit der Eigenschaft AutomaticMigrationsEnabled festgelegt, ob das Datenbankschema automatisch anhand eines Vergleichs mit den Entitätsklassen aktualisiert werden darf. Wurde diese Option aktiviert, kann das Datenbankschema jederzeit aktualisiert werden, indem die Anweisung Update-Database in der Package Manager Console aufgerufen wird (Abb. 7). Im Zuge dessen wird aus den erkannten Modifikationen eine so genannte Migration erzeugt und die Datenbank damit aktualisiert. Der Name dieser Migration wird auf der Konsole ausgegeben; Informationen zur Migration selbst werden in der automatisch eingerichteten Systemtabelle __MigrationHistory gespeichert. Wie später im Artikel beschrieben, kann zu einem späteren Zeitpunkt eine Schemaversion, die mit einer bestimmten Migration in Verbindung gebracht wird, wiederhergestellt werden, indem der Name dieser Migration beim Aufruf von Update-Database angegeben wird.

Abb. 7: Update-Database
Abb. 7: Update-Database

In Fällen, in denen die Aktualisierung des Schemas zum Verlust von Daten führen würde, ist dieser Befehl mit dem Parameter -force aufzurufen. Der Parameter -verbose führt hingegen dazu, dass die im Zuge der Schemamigration übersendeten SQL-Anweisungen auch ausgegeben werden.

Wurde AutomaticMigrationsEnabled nicht aktiviert, müssen die erkannten Modifikationen zunächst in Form einer Klasse, die die durchzuführende Migration repräsentiert, dokumentiert werden. Dazu wird der Befehl Add-Migration Migration-Name ausgeführt, wobei Migration-Name für den benutzerdefinierten Namen der Migration steht. Das Ergebnis dieser Operation ist eine Klasse, die die von der Migrationskomponente erkannten Aktualisierungen widerspiegelt (siehe Listing 11). Diese Klasse erbt von DbMigration und weist zwei überschriebene Methoden auf: Up und Down. Up wird ausgeführt, um die Migration durchzuführen, Down um sie wieder rückgängig zu machen. Der Entwickler kann diese Klasse um zusätzliche Aspekte der Migration erweitern. Im betrachteten Fall wurde zum Beispiel definiert, dass die hinzugefügte Spalte Land eine maximale Länge von 5 und den Standardwert DE haben soll. Dazu wurden der Methode String, die eine auf Strings basierende Spalte einrichtet, entsprechende Parameter verpasst. Möchte der Entwickler bestimmte SQL-Anweisungen im Zuge der Migration ausführen, kann er dies durch Aufruf der Methode Sql veranlassen.

Listing 11

namespace HotelSample.Migrations
{
    using System.Data.Entity.Migrations;
    
    public partial class Version2 : DbMigration
    {
        public override void Up()
        {
            AddColumn("Hotels", "Telefonnummer", c => c.String());
            // AddColumn("Regionen", "Land", c => c.String());
            AddColumn("Regionen", "Land", c => 
                              c.String(maxLength: 5, defaultValue:"DE"));
            
        }
        
        public override void Down()
        {
            DropColumn("Regionen", "Land");
            DropColumn("Hotels", "Telefonnummer");
        }
    }
}
  

Um alle anstehenden Migrationen durchzuführen, ist Update-Database auszuführen. Soll jedoch lediglich auf eine bestimmte Version der Datenbank migriert werden, ist der Name der gewünschten Migration im Zuge des Aufrufs von Update-Database anzugeben. Ein Aufruf von Update-Database -TargetMigration:“MyMigration“ führt zum Beispiel dazu, dass jene Version, die mit der Migration MyMigration assoziiert wird, eingespielt wird. Um eine leere Datenbank zu erhalten, kann als Migrationsname „0“ verwendet werden. Möchte man hingegen eine andere Datenbank auf den Stand einer bestimmten Version bringen, wird der Name der Verbindungszeichenkette, die in der Applikationskonfigurationsdatei zu hinterlegen ist, zusammen mit dem Parameter -TargetDatabase angegeben. Dies funktioniert auch bei automatischen Migrationen (AutomaticMigrationsEnabled ). In diesem Fall ist der Name der automatisch erzeugten Migration, der beim Ausführen von Update-Database bekannt gegeben wird, anzugeben. Ist lediglich ein SQL-Skript mit den durchzuführenden Anweisungen gewünscht, kann dies mit dem Parameter -Script angezeigt werden.

Zusammenfassung

Die aktuell zur Verfügung stehende CTP bietet einen Vorgeschmack auf verschiedene Neuerungen, die mit der nächsten Version des Entity Frameworks Einzug halten werden, darunter Unterstützung für Enums, Table-Valued Functions, Stored Procedures mit mehreren Ergebnismengen und geografische Datentypen. Auch das Aufteilen eines Entity Data Models auf verschiedene Diagramme wird in Zukunft möglich sein. Daneben bietet die Betaversion von Migrations eine elegante Möglichkeit zur Migration von Datenbankschemata.

Manfred Steyer (softwarearchitekt.at) ist freiberuflicher Trainer und Berater bei www.IT-Visions.de sowie verantwortlich für den Fachbereich Software Engineering der Studienrichtung „IT und Wirtschaftsinformatik“ an der FH CAMPUS 02 (campus02.at) in Graz. In seinem aktuellen Buch „Verteilte Systeme und Services mit .NET 4.0: Konzepte und Lösungen mit WCF 4.0“ beschreibt er gemeinsam mit Holger Schwichtenberg den gemeinsamen Einsatz von WCF, WF, WIF und Entity Framework für Unternehmensanwendungen.
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -