2014-08-27 15 views
11

ho una DatabaseInitializer classemetodo di Seed non chiamato, Entity Framework 6

public class DatabaseInitializer : CreateDatabaseIfNotExists<DatabaseContext> 
{ 
    protected override void Seed 
     (
     DatabaseContext databaseContext 
     ) 
    { 
     // Seed the hash methods. 
     var defaultHashMethod = new HashMethod 
     { 
      Description = "Default", 
      CreateDate = DateTime.Now 
     }; 

     databaseContext.HashMethod.Add(defaultHashMethod); 

     databaseContext.SaveChanges(); 
    } 
} 

Nella mia classe DatabaseContext ho impostato l'inizializzatore

public DatabaseContext() : base("DatabaseContext") 
{ 
    InitializeDatabase(); 
} 

private void InitializeDatabase() 
{ 
    Database.SetInitializer(new DatabaseInitializer()); 
    if (!Database.Exists()) 
    { 
     Database.Initialize(true); 
    }    
} 

Per quanto posso capire il metodo di seme viene richiamato solo una volta eseguita un'operazione come una query. Il mio database è stato creato con successo e sto interrogando la tabella, ma il metodo seed non viene mai chiamato.

Aggiornamento:

Sembra che il problema è causato a causa di una classe che è inheriting dal mio DatabaseContext classe, quando si utilizza questa classe per eseguire operazioni di database, il metodo di seme non viene chiamato. Quando si utilizza la mia classe DatabaseContext, tutto funziona come previsto

public DbSet<TestEntity> TestEntity { get; set; } 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
} 
+2

Hai mai trovato il modo giusto per risolvere il problema? Ho lo stesso problema. –

+0

@John Shedletsky Ho aggiunto la mia soluzione per te come risposta. – user65439

risposta

6

L'unico modo ho potuto ottenere questo lavoro è stato quello di chiamare il metodo seme me

Questi sono i metodi per la mia classe DatabaseContext

public DatabaseContext() : base("DatabaseContext") 
{ 
    InitializeDatabase(); 
} 

public DatabaseContext(string connectionString) : base(connectionString) 
{ 
    Database.Connection.ConnectionString = connectionString; 
    InitializeDatabase(); 
} 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
} 

Qui ho cambiato il mio metodo InitializeDatabase da

private void InitializeDatabase() 
{ 
    Database.SetInitializer(new DatabaseInitializer()); 
    if (!Database.Exists()) 
    { 
     Database.Initialize(true); 
    }    
} 

a

protected virtual void InitializeDatabase() 
{ 
    if (!Database.Exists()) 
    { 
     Database.Initialize(true); 
     new DatabaseInitializer().Seed(this); 
    }    
} 
+0

Grazie - Ho fatto qualcosa di simile ma più hacky, essenzialmente bruciando questa parte di EF e prendendo esplicitamente il controllo del seeding. Sembra che Update-Database utilizzi un codepath abbastanza diverso da rendere la vita infernale quando si desidera creare app non demo. –

+9

Grazie @ user65439. Sarebbe bello se lo risolvesse, ma il metodo 'Seed()' è 'protected'! Poiché si tratta di un override, non è possibile modificare l'accessor su 'public'. E poiché non è pubblico, non puoi chiamare quel metodo in 'DatabaseInitializer' dalla classe' DatabaseContext' come mostra il tuo esempio di codice (ottengo un errore di compilazione). Non capisco, cosa mi manca? – Bart

+0

Come hai risolto questo? – rolls

12

È necessario chiamare Update-Database dal Package Manager Console.

+5

Il problema è quando si esegue questa operazione il metodo seed non viene chiamato a volte. – rolls

+0

per CI, spesso non vogliamo eseguire 'Update-Database' dalla console. Molte persone preferiscono farlo automaticamente tramite le impostazioni Web/App.config. In questo modo il processo è automatizzato e puoi facilmente migrare le modifiche in un nuovo PR al DB prima dell'esecuzione dei test del PR. Altrimenti, sconfigge lo scopo della CI quando falliscono le build, richiedendo a un dev di andare a correre 'update-databse' ... –

0

Ho riscontrato questo problema e il problema era che il mio costruttore di Context non utilizzava lo stesso nome del mio web.config.

0

Se si utilizza Code-First, è possibile popolare i dati quando l'applicazione viene eseguita per la prima volta.

  • Creare un DbInitializer

    public class MyDbInitializer : IDatabaseInitializer<MyDbContext> 
    { 
        public void InitializeDatabase(MyDbContext context) 
        { 
         if (context.Database.Exists()) 
         { 
         if (!context.Database.CompatibleWithModel(true)) 
         { 
          context.Database.Delete(); 
         } 
         } 
         context.Database.Create(); 
    
         User myUser = new User() 
         { 
         Email = "[email protected]", 
         Password = "secure-password" 
         }; 
         context.Users.AddOrUpdate<User>(p => p.Email, myUser); 
         context.SaveChanges(); 
        } 
    } 
    
  • Registra questo DbInitializer nel metodo Global.asax.cs Application_Start

    Database.SetInitializer(new My.namespace.MyDbInitializer()); 
    
0

mio seme non è stato in esecuzione sia. Tuttavia, è stato perché ho aggiunto una colonna a un modello che non avevo intenzione di usare nel mio vero database e ho dimenticato di usare l'annotazione [NotMapped].

[NotMapped] 
    public string Pair { get; set; } 

Nessun messaggio di errore relativo a questa causa. Solo un riferimento null al mio repository obj quando ho provato a interrogare i dati che avrebbero dovuto essere lì.

2

per arrivare Seed metodo da chiamare quando si è non utilizzando AutomaticMigration, è necessario utilizzare MigrateDatabaseToLatestVersion inizializzatore per il database in codice prima.
come questo:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<YourContext,YourConfiguration>()); 

questo modo, Seed metodo verrà chiamato ogni volta che la migrazione è fatto con successo.

Problemi correlati