2015-02-20 17 views
6

Sto utilizzando Entity Framework 6 e sto utilizzando le migrazioni. Ho già creato il database utilizzando una migrazione iniziale. Ora ho apportato modifiche al modello e il contesto è cambiato, e voglio aggiornare il database BUT ... Quando provo a eseguire nuovamente il comando Database-Update anche le sementi sono in esecuzione, e questo porta errori dovuti ad alcuni dati inserito di nuovo.EF6 - Esegui il comando Update-Database senza semi

Quindi, come è possibile eseguire il comando Update-Database SENZA eseguire il metodo seme?


E 'difficile credere che EF non ha alcuna opzione semplice come -No-Seed per questo. Sono quasi sicuro che gli altri ORM lo facciano.

+1

Stai utilizzando il metodo di estensione 'AddOrUpdate'? – octavioccl

+0

Nop, non sto usando il 'AddOrUpdate' per tutti gli inserimenti di seed, accanto ci sono gli script slq raw. –

+0

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

risposta

7

dal codice sorgente di 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> 

Fondamentalmente, non hanno un'altra opzione di implementare una logica "aggiungere o aggiornare", perché il metodo di Seed verrà eseguita ogni volta dopo l'inizializzazione viene utilizzato .

Il metodo di estensione AddOrUpdate è utile per questo, ma ho anche usato questo in alcuni casi:

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

Yup ... ho intenzione di andare avanti e cancellare la mia risposta scritta a metà, poiché il tuo esempio di codice era esattamente quello che stavo scrivendo:) ... +1 –

+2

Giù votato perché è completamente sbagliato dire che il Il metodo Seed non verrà eseguito se non ci sono migrazioni in sospeso – Colin

+0

@Colin Hai ragione. Ho questo nel mio codice "if (migrator.GetPendingMigrations(). Any())" prima dell'esecuzione "migrator.Update()". Sto aggiornando la mia risposta. Grazie per quello. –

4

Da questa pagina: Database initializer and Migrations Seed methods:

Il metodo Seed sulle piste di classe Configuration ogni volta che viene eseguito il comando Update-Database PowerShell . A meno che non venga utilizzato l'inizializzatore Migrations , il metodo Migrations Seed non verrà eseguito all'avvio dell'applicazione .

Quindi, penso che non si dispone di molte opzioni qui, il metodo di migrazione Seed sempre verrà chiamato se si esegue Update-Database comando. Stavo scavando se esiste un parametro per questo comando che consente di specificare non eseguire il metodo Seed, ma sono fragile che non esiste ancora. Questi sono tutti i parametri che è possibile utilizzare (è possibile trovare maggiori informazioni in questo link):

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>] 

Se si esegue uno script SQL per inserire i dati nel metodo Seed, è possibile utilizzare una condizione booleam per evitare di reinserire gli stessi campi dopo la prima volta.

Come un info adizionale, la tua richiesta in avere un parametro per evitare di eseguire il metodo Seed quando si esegue il comando Update-Database già esistere in questo site, che viene utilizzato dal team di EF per raccogliere suggerimenti da parte della comunità.

1

Ho spostato tutte le mie istruzioni seed in metodi separati che possono essere commentati facilmente prima di eseguire 'update-database'.

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

Se si dispone di script SQL per inserire i dati e si desidera impedire inserimenti futuri, l'utente è possibile uno sql unire per evitare duplicati.Inserisci tutti i dati che hai in una tabella temporanea con la stessa struttura della tabella di destinazione e quindi usa l'unione per decidere quando inserire i record o meno. Se corrispondono sono perché hai inserito una volta.

Supposed S è la vostra tabella temporanea con tutti i dati e T il tavolo finale

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 

per più riferimenti utilizzare https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

0

Io di solito uso il comando update-database -sc poi ho eseguito lo script generato per aggiornare il database manualmente. Non mi sono sentito a mio agio all'inizio, ma ora mi piace vedere cosa succederà nel mio database prima che sia troppo tardi.