2015-02-20 11 views
6

Ich benutze Entity Framework 6 und ich verwende Migrationen. Ich habe die Datenbank bereits mit einer ersten Migration erstellt. Jetzt habe ich Änderungen an dem Modell vorgenommen und der Kontext hat sich geändert, und ich möchte die Datenbank aktualisieren ABER ... Wenn ich wieder versuchen, den Database-Update Befehl auszuführen, laufen auch die Seeds, und das bringt ein paar Fehler mit sich wieder eingefügt.EF6 - Ausführen Update-Datenbank Befehl ohne Samen

Also, wie kann ich den Update-Database Befehl ausführen OHNE die Seed-Methode ausführen?


Es ist schwer zu glauben, dass EF jede einfache Option nicht für die wie -No-Seed hat. Ich bin fast sicher, dass andere ORMs dies tun.

+1

Verwenden Sie die Erweiterungsmethode "AddOrUpdate"? – octavioccl

+0

Nein, ich benutze nicht 'AddOrUpdate' für alle Seed-Einfügungen, daneben gibt es rohe slq-Skripte. –

+0

http://StackOverflow.com/a/20245687/150342 – Colin

Antwort

7

Aus dem Quellcode DbMigrationsConfiguration<TContext>:

/// <summary> 
    /// Runs after upgrading to the latest migration to allow seed data to be updated. 
    /// 
    /// </summary> 
    /// 
    /// <remarks> 
    /// Note that the database may already contain seed data when this method runs. This means that 
    ///    implementations of this method must check whether or not seed data is present and/or up-to-date 
    ///    and then only make changes if necessary and in a non-destructive way. The 
    ///    <see cref="M:System.Data.Entity.Migrations.DbSetMigrationsExtensions.AddOrUpdate``1(System.Data.Entity.IDbSet{``0},``0[])"/> 
    ///    can be used to help with this, but for seeding large amounts of data it may be necessary to do less 
    ///    granular checks if performance is an issue. 
    ///    If the <see cref="T:System.Data.Entity.MigrateDatabaseToLatestVersion`2"/> database 
    ///    initializer is being used, then this method will be called each time that the initializer runs. 
    ///    If one of the <see cref="T:System.Data.Entity.DropCreateDatabaseAlways`1"/>, <see cref="T:System.Data.Entity.DropCreateDatabaseIfModelChanges`1"/>, 
    ///    or <see cref="T:System.Data.Entity.CreateDatabaseIfNotExists`1"/> initializers is being used, then this method will not be 
    ///    called and the Seed method defined in the initializer should be used instead. 
    /// 
    /// </remarks> 
    /// <param name="context">Context to be used for updating seed data. </param> 

Grundsätzlich Sie eine andere Option nicht haben, als eine „hinzuzufügen oder zu aktualisieren“ Logik zu implementieren, da die Seed-Methode jedes Mal ausgeführt wird, nachdem die Initialisierung verwendet wird, .

Die AddOrUpdate Erweiterungsmethode ist für diesen nützlich, aber ich habe dies auch in einigen Fällen verwendet:

  if (!context.Entities.Any()) 
      { 
       // Seed 
      } 
+1

Yup ... ich werde nur weitermachen und meine halb geschriebene Antwort löschen, da Ihr Codebeispiel genau das war, was ich geschrieben habe:) ... +1 –

+2

Gestimmt, weil es völlig falsch ist, das zu sagen Seed-Methode wird nicht ausgeführt, wenn keine Migrationen anstehen – Colin

+0

@Colin Sie haben Recht. Ich habe dies in meinem Code "if (migrator.GetPendingMigrations(). Any())" vor der Ausführung von "migrator.Update()". Ich aktualisiere meine Antwort. Dank dafür. –

4

Von dieser Seite: Database initializer and Migrations Seed methods:

Die Seed Methode auf der Configuration Klasse läuft Immer wenn der Update-Database PowerShell Befehl ausgeführt wird. Wenn der Migrationsinitialisierer nicht verwendet wird, wird die Migrationsmethode Seed nicht ausgeführt, wenn Ihre Anwendung startet.

Also, ich glaube, Sie haben nicht viele Optionen hier, die Migration Seed Methode wird immer dann aufgerufen, wenn Sie Update-Database Befehl ausführen. Ich habe gegraben, wenn ein Parameter zu diesem Befehl vorhanden ist, der Sie die Methode Seed nicht ausführen lassen, aber ich bin fraid es existiert noch nicht. Dies sind alle Parameter, die Sie verwenden können (können Sie weitere Informationen in diesem link finden):

Update-Database [-SourceMigration <String>] [-TargetMigration <String>] [-Script] [-Force] 
    [-ProjectName <String>] [-StartUpProjectName <String>] [-ConfigurationTypeName <String>] 
    [-ConnectionStringName <String>] [-AppDomainBaseDirectory <String>] [<CommonParameters>] 

Update-Database [-SourceMigration <String>] [-TargetMigration <String>] [-Script] [-Force] 
    [-ProjectName <String>] [-StartUpProjectName <String>] [-ConfigurationTypeName <String>] 
    -ConnectionString <String> -ConnectionProviderName <String> 
    [-AppDomainBaseDirectory <String>] [<CommonParameters>] 

Wenn Sie die Ausführung eines SQL-Skript zum Einfügen von Daten in der Seed Methode, könnten Sie eine booleam Bedingung verwenden reinsert zu vermeiden die gleichen Felder nach dem ersten Mal.

Als aditional Info, Ihre Anfrage in eine Parameter die Seed Methode ausführen zu vermeiden, wenn Sie den Befehl ausführen Update-Database existieren bereits in diesem site, die von EF-Team verwendet wird Vorschläge aus der Community zu sammeln.

1

Ich habe alle meine Seed-Anweisungen in separate Methoden verschoben, die einfach auskommentiert werden können, bevor 'update-database' ausgeführt wird.

protected override void Seed(Tpsc.EDI.EDIContext context) 
{ 
    try 
    { 
     //EDI.Seed.DoSeed(context); 
    } 
    catch (DbEntityValidationException e) 
    { 
     ... 
    } 
} 
0

Wenn Sie SQL-Skripte haben die Daten einzufügen, und Sie wollen künftig Einfügungen verhindern, die Sie Benutzer kann eine SQL fusionieren Duplikate zu vermeiden.Fügen Sie alle Daten, die Sie in einer temporären Tabelle haben, mit derselben Struktur Ihrer Zieltabelle ein und verwenden Sie dann die Zusammenführung, um zu entscheiden, wann Sie die Datensätze einfügen werden oder nicht. Wenn sie übereinstimmen, liegt das daran, dass du einmal eingefügt hast.

Vermeintliche S ist Ihre temporäre Tabelle mit allen Daten und T Final Table

MERGE Target AS T 
USING Source AS S 
ON (T.EmployeeID = S.EmployeeID AND T.EmployeeName LIKE 'S%' 
    AND S.EmployeeName LIKE 'S%') 
WHEN NOT MATCHED BY TARGET 
    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName) 
WHEN MATCHED 
    THEN UPDATE SET T.EmployeeName = S.EmployeeName 
WHEN NOT MATCHED BY SOURCE 
    THEN DELETE 

für weitere Referenzen verwenden https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

0

ich in der Regel verwenden Sie den Befehl update-database -sc dann betreibe ich das Skript-Datenbank zu aktualisieren erzeugt manuell. Ich fühlte mich nicht wohl, dies am Anfang zu tun, aber jetzt möchte ich sehen, was mit meiner Datenbank passieren wird, bevor es zu spät ist.