2012-02-18 17 views
41

Ho utilizzato Entity Framework 4.3 su un database esistente e ho un paio di scenari che sto cercando di soddisfare.Il modo migliore per eseguire l'inizializzazione dei dati in Entity Framework 4.3

In primo luogo, se elimino il mio database vorrei ricrearlo da zero - Ho usato con successo un inizializzatore del database CreateDatabaseIfNotExists per questo.

In secondo luogo, se aggiorno il mio modello e il database esiste già vorrei che il database venisse aggiornato automaticamente - Ho utilizzato con successo Entity Framework 4.3 Migrations per questo.

Quindi ecco la mia domanda. Suppongo di aggiungere una nuova tabella al mio modello che richiede alcuni dati di riferimento, quale è il modo migliore per garantire che questi dati vengano creati sia quando viene eseguito l'intialiser del database sia quando viene eseguita la migrazione. Il mio desiderio è che i dati vengano creati quando creo il db da zero e anche quando il database viene aggiornato come risultato di una migrazione in esecuzione.

In alcuni esempi di migrazioni EF ho visto persone utilizzare la funzione SQL() nel metodo UP della migrazione per creare i dati seme ma, se possibile, preferirei utilizzare il contesto per creare i dati seme (come si vede nella maggior parte esempi di inizializzazione del database), poiché mi sembra strano che si utilizzi pure sql quando l'intera idea di EF lo sta allontanando. Ho provato a utilizzare il contesto nel metodo UP ma per qualche motivo non pensavo che esistesse una tabella creata nella migrazione quando ho provato ad aggiungere i dati seme direttamente sotto la chiamata per creare la tabella.

Ogni saggezza ha molto apprezzato.

risposta

53

Se si desidera utilizzare le entità per i dati di inizializzazione, utilizzare il metodo Seed nella configurazione delle migrazioni. Se si genera nuovo progetto Enable-Migrations otterrete questa classe di configurazione:

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

    protected override void Seed(CFMigrationsWithNoMagic.BlogContext context) 
    { 
     // This method will be called after migrating to the latest version. 

     // You can use the DbSet<T>.AddOrUpdate() helper extension method 
     // to avoid creating duplicate seed data. E.g. 
     // 
     // context.People.AddOrUpdate(
     //  p => p.FullName, 
     //  new Person { FullName = "Andrew Peters" }, 
     //  new Person { FullName = "Brice Lambson" }, 
     //  new Person { FullName = "Rowan Miller" } 
     // ); 
     // 
    } 
} 

Il modo in cui i dati di semi le migrazioni non sono molto efficienti perché si suppone ad essere utilizzato per un po 'di semina molto di base. Ogni aggiornamento alla nuova versione passerà attraverso l'intero set e tenterà di aggiornare i dati esistenti o inserire nuovi dati. Se non si utilizza il metodo di estensione AddOrUpdate, è necessario assicurarsi manualmente che i dati vengano inoltrati al database solo se non sono ancora presenti.

Se volete modo efficace per la semina in quanto è necessario seminare o molti dati si otterrà una migliore risultato con comuni:

public partial class SomeMigration : DbMigration 
{ 
    public override void Up() 
    { 
     ... 
     Sql("UPDATE ..."); 
     Sql("INSERT ..."); 
    } 

    public override void Down() 
    { 
     ... 
    } 
} 
+8

È possibile creare un contesto nel metodo Su e utilizzare AddOrUpdate per inserire righe. Tuttavia, questo non sarà incluso nella transazione di migrazione, quindi può causare problemi. Inoltre non è garantito la compilazione in futuro quando il modello cambia. – Betty

+0

Ho provato a creare un contesto nel metodo Su, ma ha generato un errore che diceva che la tabella non esisteva. Proverò SQL nel metodo "Su" invece. –

+8

@Ladislav la tua conoscenza approfondita su EF continua a stupirmi, hai considerato di creare un libro sull'argomento e forse affrontare i comuni fraintendimenti che incontri qui? – kingdango

32

non consiglierei utilizzando Sql() chiamate nel metodo Up() perché (IMO) questo è realmente inteso per il codice di migrazione effettivo per il quale non esiste una funzione incorporata, piuttosto che un codice seme.

Mi piace pensare ai dati seme come a qualcosa che potrebbe cambiare in futuro (anche se il mio schema non funziona), quindi scrivo semplicemente controlli "difensivi" attorno a tutti i miei inserti nella funzione seme per assicurarmi che il operazione non ha sparato in precedenza.

Si consideri uno scenario in cui si dispone di una tabella "Tipi" che inizia con 3 voci, ma successivamente si aggiunge un 4 °. Non dovresti aver bisogno di una "migrazione" per risolvere questo problema.

L'utilizzo di Seed() offre anche un contesto completo con cui lavorare, che è molto più bello rispetto all'utilizzo delle stringhe sql semplici nel metodo Sql() dimostrato da Ladislav.

Inoltre, tenere presente che il vantaggio dell'utilizzo di metodi EF incorporati sia per il codice di migrazione sia per il codice di inizializzazione è che le operazioni del database rimangono neutre rispetto alla piattaforma. Ciò significa che le modifiche dello schema e le query possono essere eseguite su Oracle, Postgre, ecc. Se si scrive l'SQL raw effettivo, è possibile bloccarsi inutilmente.

Si potrebbe essere meno preoccupati di questo poiché il 90% delle persone che utilizzano EF colpirà solo SQL Server, ma lo sto lanciando solo per darvi una prospettiva diversa sulla soluzione.

+7

Penso che il metodo "Su" sia un buon posto per fare dati "di riferimento" - i dati di riferimento in genere implicano che l'applicazione richiede tali dati per una sorta di logica. – nootn

Problemi correlati