wake-up-neo.com

Entity Framework Code-First: Wie aktualisiere ich die Datenbank manuell?

Ich habe eine kleine WPF-Demo-App erstellt, die EF Code-First verwendet, um ihre Daten in einer SQL CE 4.0-Datenbank zu speichern. Es funktioniert einwandfrei, es sei denn, ich entferne eine Eigenschaft aus einem Modellobjekt. Zum Beispiel, wenn ich "HosteBy" aus dieser Klasse entferne .....

public class Dinner
{
    public int DinnerID { get; set; }
    public string Title { get; set; }   
    public DateTime EventDate { get; set; }
    public string Address { get; set; }
    public string HostedBy { get; set; }

    public virtual ICollection<RSVP> RSVPs { get; set; }
}

... es löst diese Ausnahme aus:

Das Modell, das den Kontext "NerdDinners" unterstützt, hat sich seit der Erstellung der Datenbank geändert. Löschen/aktualisieren Sie die Datenbank manuell oder rufen Sie Database.SetInitializer mit einer IDatabaseInitializer-Instanz auf. Beispielsweise löscht und erstellt die DropCreateDatabaseIfModelChanges-Strategie die Datenbank automatisch und erstellt sie neu. Optional können neue Daten hinzugefügt werden.

Der Fehler bleibt auch nach dem manuellen Entfernen des Feldes "HosteBy" aus der Datenbank bestehen. Was vermisse ich hier? Muss ich die Datenbank löschen/kürzen oder gibt es eine andere Lösung?

21
Mike

Im ersten Szenario, in dem Sie das Code First Model geändert haben, bevor Sie die Datenbank manuell geändert haben, müssen Sie die (Nuget) Package Manager Console öffnen und Folgendes eingeben:

update-database -verbose

Ausnahme: Da Sie in diesem Fall eine Spalte entfernen, wird gemeldet, dass etwas gelöscht wird. Sie wird nichts löschen, ohne dass Sie ausdrücklich sagen, dass dies in Ordnung ist. Sie geben also ein:

update-database -f -verbose

Jetzt wird die Spalte gelöscht, die Sie in Ihrem Modell hatten. -verbose sagt Ihnen, welche SQL es ausführt. Wenn Sie Angst davor haben, Dinge einfach löschen zu lassen und SQL vor der Ausführung zu überprüfen, verwenden Sie Folgendes:

update-Datenbank -f-Skript

Stattdessen wird die SQL-Anweisung an ein Skript ausgegeben, über das Sie nachsehen können, und das manuell ausgeführt wird.

In dem Fall, in dem Sie die Spalte in der Datenbank manuell gelöscht haben, haben Sie jetzt ein komplexeres Szenario in der Hand. Die in der anderen Antwort hier beschriebene Tabelle EdmMetadata enthält einen Hash der gesamten Datenbank, der jetzt nicht mit der Datenbank selbst übereinstimmt. Sie können manuelles SQL ausführen, um die Datenbank auf die Art und Weise wiederherzustellen, wie sie von Entity Framework erwartet wird (wie vor der manuellen Änderung vor dem Ändern, was sie an den Hash anpasst), indem Sie überprüfen, was Sie zuvor hatten und wie Ihre Datenbank aktuell aussieht.

Wenn dies nicht möglich ist, befinden Sie sich jetzt im hässlichsten Teil von Entity Framework Code First. Sie müssen die Hashtabelle entfernen und die Datenbank in Codedateien zurückentwickeln.

Der Name der Hashtabelle hängt von der Version von EF ab. In älteren EF4, wie Sie gefragt haben, heißt es EdmMetadata. In neueren EF5 heißt es __MigrationHistory (unter Systemtabellen in Ihrer Datenbank, wenn Sie in SQL Server Management Studio suchen). Sie müssen es auslöschen.

Die gute Nachricht für den zweiten Schritt, die Rückwärtsentwicklung der Datenbank in Code, ist, dass Microsoft ein Beta-Tool veröffentlicht hat, das dies für Sie tun wird.

Walk-Through von Reverse-Engineering a Db und EF Power Tools

Sie können viele der ersten Schritte dort überspringen, da sie lediglich eine Datenbank einrichten und etwas Unsinn hinzufügen, um zu zeigen, was Sie tun müssen: Reverse Engineer a db.

Aktualisieren:

Es kann auch möglich sein, eine manuelle Migration zu verwenden, um dieses Szenario zu umgehen. Erstellen Sie eine Sicherungskopie der Datenbank, und führen Sie dann Folgendes aus:

add-migration WhateverYouWantToCallThis

Die Änderungen an den db EF-Migrationen, die ausgeführt werden müssen, werden in den generierten C # -Befehlen angezeigt. Nun liegt es an Ihnen, mit ihnen zu basteln, um sowohl die Probleme mit dem, was sie zu tun versucht, zu umgehen (zum Beispiel den Versuch, bereits gelöschte Spalten zu löschen), als auch Dinge zu implementieren, die erforderlich sind (z. B. Hinzufügen) eine Tabelle, die Sie noch in Ihrem Modell haben, die Sie jedoch manuell in Ihrer Datenbank gelöscht haben).

Sobald Sie dies hinzugefügt und update-database -f ausgeführt haben, akzeptiert EF Code First nur das Vertrauen, dass Sie die Datenbank so aktualisiert haben, wie sie sein muss, und aktualisiert den Hashwert basierend auf dem Endergebnis. Wenn Sie die richtigen Änderungen vorgenommen haben, können Sie mit den Migrationen wie gewohnt fortfahren. Wenn dies immer noch zu Fehlern führt, können Sie die Befehle der manuellen Migration normalerweise irgendwo herauskopieren und löschen. Wiederherstellen der Datenbank aus der Sicherung, fügen Sie erneut eine manuelle Migration hinzu und versuchen Sie es erneut. Im schlimmsten Fall greifen Sie auf den umgekehrten Engineering-Schritt zurück.

25
Chris Moschini
3
Manatherin

Wenn Ihre Datenbank eine seltsame Tabelle mit dem Namen EdmMetadata enthält, verwendet Ihr Kontext eine sehr grundlegende Version der Datenbankversionierung. Beim Erstellen der Datenbank wurde ein Hash Ihres Modells in dieser Tabelle gespeichert. Jedes Mal, wenn ein Modell für Ihre Anwendung erstellt wird (wenn Sie den Kontext zum ersten Mal verwenden, nachdem Sie Ihre Anwendung neu gestartet haben), berechnet es den Hash erneut und vergleicht ihn mit dem in ihm gespeicherten Hash dieser Tisch. Dies bedeutet, dass jede Änderung in Ihrem Modell zu einem anderen Hash führt und EF mit der Ausnahme reagiert, die Sie sehen. Eine manuelle Änderung in der Datenbank hilft Ihnen nicht, da die Tabelle noch die alte enthält.

Die Lösungen sind:

  • Diese Versionierung entfernen Es erfordert das Entfernen von IncludeMetadataConvention wie beschrieben hier .
  • Aktualisieren des Hashes Es ist erforderlich, den Algorithmus für die Hashberechnung (z. B. durch Red Gate .NET Reflector, JetBrains dotPeek, SharpDevelop ILSpy oder Telerik JustDecompile) umzuentwickeln und einen neuen Hash aus dem kompilierten Modell zu berechnen (oder Reflektion verwenden, um die interne Eigenschaft von DbCompiledModel.ModelHash mit bereits berechnetem zu lesen Hash), den Sie in der Tabelle EdmMetadata speichern.
  • Löschen Sie die Datenbank manuell und lassen Sie EF eine neue erstellen - Sie verlieren alle Daten
  • Wenn Sie den Initialisierer auf DropCreateDatabaseIfModelChanges setzen, wird die Datenbank automatisch gelöscht und eine neue erstellt, wenn Sie das Modell ändern. Sie verlieren alle Daten
2
Ladislav Mrnka

Drei einfache Dinge, die Sie bei der Arbeit mit Code First beachten sollten

  1. Aktivieren Sie Migrationen 
  2. Add-Migration
  3. Datenbank auf den neusten Stand bringen

Alles ist selbsterklärend.

Sie müssen diese Befehle manuell in der Package Manager Console ausführen. Ich komme zu spät, hoffe jedoch, dass dies helfen wird 

0
Ali Adravi

In diesem Artikel finden Sie Informationen zu ersten Migrationen mit einer vorhandenen Datenbank
http://msdn.Microsoft.com/en-us/data/dn579398

Manchmal sind Ihr Projekt und Ihre Datenbank möglicherweise nicht mehr synchron. Daher müssen Sie möglicherweise Ihr Schema auf der Grundlage Ihrer vorhandenen Datenbank erneut synchronisieren.



1) So erstellen Sie eine Migration basierend auf dem vorhandenen Schema: 
Add-Migration InitialCreate

2) Führen Sie danach Update-Database aus, um den Eintrag zur Tabelle _MigrationsHistory hinzuzufügen, um anzuzeigen, dass die Migration bis zum vorhandenen Schema abgeschlossen ist.

0
WWC