EF5 – “model first” Datenbank Updates mit VS 2012


Nach einem guten Abend an Recherchearbeit, um herauszufinden ob es möglich ist, dass man evtl. direkt im EF5 Framework oder über EF Tools die Möglichkeit hat für den “model first” Ansatz seine Datenbank nach einer Modeländerung zu aktualisieren. Habe ich leider keine Integrierte Lösung finden können. Wenn hier jemand andere Erfahrungen gemacht hat, dann freue ich mich hier sehr über einen passenden Lösungsvorschlag oder Ansatz.

Außerdem habe ich einen Feature Request auf der EF Seite dafür gestartet und ich freue mich über jeden Vote, den ich bekommen kann für den Request, Voten könnt Ihr ohne euch anzumelden auf der folgenden Seite:

http://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/3065564-ef5-model-first-genrate-db-update-script

Visual Studio – SQL Schemavergleich zum Aktualisieren der Datenbank

Die einzige Lösung die ich hier aktuell vorschlagen kann, ist es den Integrierten Schemavergleich im Visual Studio für Datenbankupdates zu nutzen.

Nachteile dieser Lösung:

  • Nicht direkt in den EF Modellierungsprozess eingebunden
  • Man benötigt zwei Datenbanken – einmal die Originaldatenbank die aktualisiert werden soll und dann die neue Datenbank mit allen Updates, damit ein Vergleich erstellt werden kann mit der Originaldatenbank.

Wichtige Hinweise beim Durchführen von Modelländerungen im edmx Model

Außerdem muss darauf geachtet werden, wenn man in einem edmx Modell einer Klasse neue Member hinzufügt. Hier muss “Null” angegeben werden oder ein Default Wert hinterlegt werden. Denn sonst kann später kein Updatescript vom Schemavergleich erstellt werden. Im edmx Model können zwar Standardwerte eingestellt werden, diese werden jedoch nicht im generierten SQL eingebunden. Daher muss dies von Hand angepasst werden.

Im Folgenden lege ich für den Namen den Standardwert “Maus” fest, wenn man dann aber über

image

“Datenbank aus Modell generieren” das passende SQL Script generieren lässt,

image

dann sieht der Teil in dem die Tabelle angelegt wird folgendermaßen aus:

-- Creating table 'TiereSatz'
CREATE TABLE [dbo].[TiereSatz] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [Name] nvarchar(max)  NOT NULL,
    [Art] nvarchar(max)  NOT NULL
);

Hier wird aber das Folgende Script benötigt, damit später auch ein Updatescript erstellt werden kann, denn wenn in der jeweiligen Tabelle der späteren Zieldatenbank bereits Werte enthalten sind, kann kein Update durchgeführt werden. Da z.B. schon die Tabelle existierte mit dem Member “Art” und hier bereits Werte eingetragen sind muss bei einem Update entweder der default Wert gesetzt werden oder null zugelassen sein für die neue Spalte “Name”.

-- Creating table 'TiereSatz'
CREATE TABLE [dbo].[TiereSatz] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [Name] nvarchar(max)  NOT NULL default 'Maus',
    [Art] nvarchar(max)  NOT NULL
);

Der “Name” kann auch ”Null” sein, dann gibt es keine Probleme beim Hinzufügen der Spalte, wenn man im Designer “Null-Werte zulassen” auf “True” stellt, dann wird das folgende Script generiert welches auch funktioniert.

-- Creating table 'TiereSatz'
CREATE TABLE [dbo].[TiereSatz] (
    [ID] int IDENTITY(1,1) NOT NULL,
    [Name] nvarchar(max)  NULL,
    [Art] nvarchar(max)  NOT NULL
);

Erstellen des Schema Vergleiches mit Visual Studio und Updaten der DB

Sobald beide Datenbanken eingerichtet sind, zum einen die “alte” Datenbank die aktualisiert werden soll und die “neue” Datenbank in der alle Änderungen enthalten sind, dann können wir im Visual Studio im Menü einen neuen Schemavergleich erstellen.

image

Hier kann man jetzt das Ziel und die Quelldatenbank auswählen

image

Die Quelle ist bei uns die “neue” Datenbank die alle Updates enthält und das Ziel ist bei und die “alte” Datenbank in der die Änderungen durchgeführt werden sollen.

Die Auswahl der passenden DB findet über ein einfaches Menü statt.

image

und sobald beide Datenbanken ausgewählt wurden, steht die Funktion “Vergleichen” zur Verfügung

image

Wenn der Vergleich ausgeführt wurde, steht einem die Aktualisieren Funktion zur Verfügung oder das Erstellen eines SQL Scripts, welches man sich anschauen kann und dann meist schon in den ersten Zeilen erkennt ob es ein erfolgreiches update wird oder nicht.

image

Wenn man auf aktualisieren klickt, sieht man im VS dann auch ob alles geklappt hat

image

Jetzt sind beide Datenbanken auf dem „gleichen” Stand, was zumindest die Tabellen und Verknüpfungen betrifft.

Beispiel für einen Fehlschlag des Updates:

Wenn eine Aktualisierung fehlschlägt, empfehle ich das man sich das Update Script ausgeben lässt, damit man sieht wo der Fehler aufgetreten ist.

Das folgende generierte SQL Update Script kann nicht erfolgreich ausgeführt werden, da ich in der Tiertabelle die Spalte “Name” auf “Not Null” gesetzt habe. Hier kann man sehr gut erkennen wo der Fehler liegt und man kann dann im edmx Model oder dem Script für das Erstellen der neuen Datenbank die passenden Änderungen vornehmen und hier wieder testen ob ein Update möglich ist.

/*
Die Spalte "[dbo].[TiereSatz].[Vorname]" in der Tabelle "[dbo].[TiereSatz]" muss hinzugefügt werden,
besitzt jedoch keinen Standardwert und unterstützt keine NULL-Werte. Wenn die Tabelle Daten enthält,
funktioniert das ALTER-Skript nicht. Um dieses Problem zu vermeiden, müssen Sie der Spalte einen
 Standardwert hinzufügen, sie so kennzeichnen, dass NULL-Werte zulässig sind, oder die Generierung
 von intelligenten Standardwerten als Bereitstellungsoption aktivieren.
*/

IF EXISTS (select top 1 1 from [dbo].[TiereSatz])
    RAISERROR (N'Zeilen wurden erkannt. Das Schemaupdate wird beendet, da es möglicherweise zu einem Datenverlust kommt.', 16, 127) WITH NOWAIT
GO

Advertisements

7 Gedanken zu „EF5 – “model first” Datenbank Updates mit VS 2012

  1. efuser

    Naja, man könnte sich aus einem *.edmx File auch Code-First Klassen generieren lassen!?
    Dann könnte man nämlich auch die EF Migrations benutzen…

    Oder steht das in diesem Fall nicht zur Verfügung?

    Gefällt mir

    Antwort
  2. SquadWuschel Autor

    EF Migrations habe ich schon rumgespielt, aber mit Model First geht das nicht. Ich wüsste auf Anhieb nicht wie man sich Code First Klassen generieren lassen kann aus Model First, hast du da bereits Erfahrungen mit gemacht?

    Das einzige was ich so spontan gefunden habe wäre der Folgende Link: http://weblogs.asp.net/jgalloway/archive/2011/02/24/generating-ef-code-first-model-classes-from-an-existing-database.aspx

    Hier scheint der Aufwand jedes mal aber genauso groß wie den, den ich hier bereits beschrieben habe.

    Gefällt mir

    Antwort
    1. SquadWuschel Autor

      Ja die habe ich mir auch angeschaut, konnte aber keine nützlichen Eigenschaften für die Zusammenarbeit mit „model first“ finden.

      Da müsstest du mir evtl. einen detaillierteren Tipp geben, denn die Tools helfen einem nur für POCO und co weiter.

      Gefällt mir

      Antwort
  3. SquadWuschel Autor

    Hio, den DbContext Generator verwende ich bereits in meinen Projekten und leider wird der nicht akzepitert von EF Migrations. Zumindest nicht die Standardvorgehensweise die ich verwende, so wie es im Tool beschrieben wird. Die EF Migrations funktionieren nur mit dem DbContext aber nicht mit dem automatisch generierten. Meiner Erfahrung nach zumindest, wenn man hier was spezielles beachten muss damit die Migrations funktionieren, dann wäre ich für einen Tipp dankbar.

    Gefällt mir

    Antwort
    1. efuser

      Achso, ok – das könnte sein. Vlt. funktioniert es ja, wenn du die generierten Klassen herauskopierst aus dem Generator. Dann könnte dies schon funktionieren. Ich muss allerdings sagen, das habe ich selbst noch nicht getestet.

      Gefällt mir

      Antwort

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s