Comment créer un initializer pour créer et migrer la firebase database mysql?

J’ai appris à utiliser EF pendant environ une semaine et je suis bloqué sur la question de la création / mise à jour de ma firebase database. Je suis capable de créer un initialiseur pour créer la firebase database si ce n’est pas là:

static class Program { static void Main() { Database.SetInitializer(new GumpDatabaseInitializer()); .... class GumpDatabaseInitializer : CreateDatabaseIfNotExists { public GumpDatabaseInitializer() { } protected override void Seed(GumpDatabase context) { context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)"); // Other stuff } } 

Ou je peux créer une configuration pour migrer la firebase database

 static class Program { static void Main() { Database.SetInitializer(new MigrateDatabaseToLatestVersion()); .... internal sealed class Configuration : DbMigrationsConfiguration { public Configuration() { AutomaticMigrationsEnabled = true; SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator()); } protected override void Seed(GumpDatabase context) { } 

Chacun fonctionne correctement mais je n’ai pas trouvé de moyen de faire les deux. Je peux basculer entre les deux initialiseurs en modifiant l’appel SetInitializer mais si je veux créer la firebase database si elle n’est pas présente et la migrer également si c’est ce que je fais? Dois-je créer un initialiseur personnalisé?

Merci

Modification basée sur la réponse de NSGaga

 class CreateOrMigrateDatabaseInitializer : CreateDatabaseIfNotExists, IDatabaseInitializer where TContext : DbContext where TConfiguration : DbMigrationsConfiguration, new() { private readonly DbMigrationsConfiguration _configuration; public CreateOrMigrateDatabaseInitializer() { _configuration = new TConfiguration(); } public CreateOrMigrateDatabaseInitializer(ssortingng connection) { Contract.Requires(!ssortingng.IsNullOrEmpty(connection), "connection"); _configuration = new TConfiguration { TargetDatabase = new DbConnectionInfo(connection) }; } void IDatabaseInitializer.InitializeDatabase(TContext context) { Contract.Requires(context != null, "context"); if (context.Database.Exists()) { if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false)) { var migrator = new DbMigrator(_configuration); migrator.Update(); } } else { context.Database.Create(); Seed(context); context.SaveChanges(); } } protected virtual void Seed(TContext context) { } } 

et

 internal sealed class Configuration : DbMigrationsConfiguration { public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = false; SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator()); } protected override void Seed(GumpDatabase context) { } } 

et

 class GumpDatabaseInitializer : CreateOrMigrateDatabaseInitializer { public GumpDatabaseInitializer() { } protected override void Seed(GumpDatabase context) { context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)"); context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Sequences (Name)"); context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX StationPartNumber ON StationPartNumbers (StationId,PartNumberId)"); } } 

et enfin

 static void Main() { Database.SetInitializer(new GumpDatabaseInitializer()); 

Je pense que vous êtes à peu près là – vous pouvez rechercher le code source de MigrateDatabaseToLatestVersion (c’est open source http://entityframework.codeplex.com/ ) – c’est assez simpliste, ce qui est plutôt appelé le DbMigrator – en ce qui concerne Je pourrais voir.

Tout ce que vous avez à faire semble être de fusionner les deux – utilisez l’un ou l’autre comme base, ajoutez-y d’autres fonctionnalités – cela devrait bien fonctionner, je pense.

 class CreateAndMigrateDatabaseInitializer : CreateDatabaseIfNotExists, IDatabaseInitializer where TContext : DbContext where TConfiguration : DbMigrationsConfiguration, new() { private readonly DbMigrationsConfiguration _configuration; public CreateAndMigrateDatabaseInitializer() { _configuration = new TConfiguration(); } public CreateAndMigrateDatabaseInitializer(ssortingng connection) { Contract.Requires(!ssortingng.IsNullOrEmpty(connection), "connection"); _configuration = new TConfiguration { TargetDatabase = new DbConnectionInfo(connection) }; } void IDatabaseInitializer.InitializeDatabase(TContext context) { Contract.Requires(context != null, "context"); var migrator = new DbMigrator(_configuration); migrator.Update(); // move on with the 'CreateDatabaseIfNotExists' for the 'Seed' base.InitializeDatabase(context); } protected override void Seed(TContext context) { } } 

Appelez comme ça …

 Database.SetInitializer(new CreateAndMigrateDatabaseInitializer()); 

… en fait, remplacez-le (puisqu’il s’agit d’une implémentation générique) comme vous le faisiez pour CreateDatabaseIfNotExists (vous avez simplement un “param” supplémentaire pour la configuration) – et fournissez simplement le “Seed”.

 class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer { protected override void Seed(GumpDatabase context) { context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)"); } } 

… et l’appeler quelque chose comme

 Database.SetInitializer(new GumpDatabaseInitializer()); 

EDIT: Selon les commentaires – DbMigrator ne devrait pas être exécuté deux fois. Il vérifie toujours (passe un peu de temps) et fait une mise à jour «vierge» et passe à autre chose. Cependant, juste au cas où vous voudriez enlever ça et “cocher” avant d’entrer – ça devrait marcher (changer la pièce similaire ci-dessus) …

 var migrator = new DbMigrator(_configuration); if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false)) if (migrator.GetPendingMigrations().Any()) migrator.Update(); 

(ceci est une redondance / double vérification – un des if-s devrait suffire. Mettez une pause là-bas – et voyez ce qui se passe exactement, cela ne devrait pas entrer – une fois que Db est migré. Comme je l’ai mentionné, fonctionne bien lorsque Essaye-le.

MODIFIER:

Remplacer l’intérieur de InitializeDatabase par …

 var doseed = !context.Database.Exists(); // && new DatabaseTableChecker().AnyModelTableExists(context); // check to see if to seed - we 'lack' the 'AnyModelTableExists' - could be copied/done otherwise if needed... var migrator = new DbMigrator(_configuration); // if (doseed || !context.Database.CompatibleWithModel(throwIfNoMetadata: false)) if (migrator.GetPendingMigrations().Any()) migrator.Update(); // move on with the 'CreateDatabaseIfNotExists' for the 'Seed' base.InitializeDatabase(context); if (doseed) { Seed(context); context.SaveChanges(); } 

Cela fonctionne (à mi-chemin) sans semis – si la migration commence en premier. Et les migrations doivent être les premières, sinon vous avez des problèmes.

Vous devez toujours le faire correctement – c’est l’essentiel si ce n’est tout ce dont vous pourriez avoir besoin – mais si vous rencontrez des problèmes avec MySQL etc.

Remarque: la dissortingbution continue de ne pas appeler si vous avez une firebase database, mais elle est vide. Le problème est le mélange des deux initialiseurs différents. Vous devrez donc résoudre ce problème – en implémentant ce que Create … fait à l’intérieur (cet appel que nous ne pouvons pas appeler) ou autre chose.

En fait, cela devrait être:

 var migrator = new DbMigrator(_configuration); if (!context.Database.CompatibleWithModel(false) || migrator.GetPendingMigrations().Any()) migrator.Update(); 

car si nous avons une migration qui n’est pas liée à notre modèle de firebase database, par exemple l’insertion d’une ligne dans aucune de nos tables, la migration ne sera pas exécutée.

Pour faire les deux (amorçage et migration), vous devez uniquement utiliser les migrations avec un initialiseur MigrateDatabaseToLatestVersion . Lorsque vous activez les migrations pour votre contexte, une classe de Configuration dérivée de DbMigrationsConfiguration est créée et vous pouvez remplacer la méthode Seed pour initialiser votre firebase database. Notez que la firebase database peut déjà contenir des données de départ lorsque cette méthode est AddOrUpdate mais que la méthode d’extension AddOrUpdate vous aide commodément à effectuer des “upserts” dans votre firebase database.

Ceci est différent par rapport à la méthode Seed de certains des autres intitializers de la firebase database, dans laquelle la firebase database n’est semée que lorsqu’elle a été créée. Toutefois, lorsque vous utilisez des migrations, vous souhaiterez peut-être modifier vos données de base lorsque la firebase database sera MigrateDatabaseToLatestVersion utilisation de MigrateDatabaseToLatestVersion rend cela possible.

Pour combiner l’amorçage avec les migrations, vous devez effectuer les étapes suivantes dans un nouveau projet:

  1. Créer un DbContext code- DbContext avec des entités associées

  2. Dans la console du gestionnaire de packages, exécutez la commande Enable-Migrations

  3. Dans le dossier Migrations , une classe de Configuration est générée avec une méthode Seed . Vous pouvez modifier cette méthode pour créer votre firebase database:

     protected override void Seed(MyContext context) { // Add two entities with name "Foo" and "Bar". context.MyEntities.AddOrUpdate( e => e.Name, new MyEntity { Name = "Foo" }, new MyEntity { Name = "Bar" } ); } 
  4. Vous devez créer un initialiseur de firebase database dérivé de MigrateDatabaseToLatestVersion :

     class MyContextInitializer : MigrateDatabaseToLatestVersion { } 

    Vous devrez également configurer l’initialiseur en appelant Database.SetInitializer(new MyContextInitializer()) démarrage de votre application ou dans le fichier App.config à l’aide de l’élément .

  5. Dans le constructeur de la classe de Configuration générée, vous pouvez activer les migrations automatiques:

     public Configuration() { AutomaticMigrationsEnabled = true } 

    Cependant, dans une équipe, vous préférerez peut-être ne pas le faire. Dans ce cas, vous devrez créer une migration initiale (sauf si elle a été créée lorsque vous avez activé Enable-Migrations ). Dans le gestionnaire de packages, exécutez la commande Add-Migration InitialCreate . Cela crée la première migration requirejse pour créer votre firebase database.

À ce stade, vous avez un DbContext avec des migrations et une méthode Seed .

Donc, pour résumer: Activez les migrations, utilisez l’initialiseur MigrateDatabaseToLatestVersion et ajoutez des données de base dans la classe de Configuration générée lors de l’activation des migrations.

Si MigrateDatabaseToLatestVersion crée effectivement la firebase database si elle n’existe pas et vous permet même de l’ensemencer, si vous disposez déjà d’une solution opérationnelle basée sur CreateDatabaseIfNotExists et / ou si vous ne souhaitez pas la compliquer en testant l’existence de données de base, vous pouvez: utilisez simplement le texte ci-dessous en héritant de celui-ci plutôt que de CreateDatabaseIfNotExists :

 public class CreateOrMigrateDatabaseInitializer : CreateDatabaseIfNotExists, IDatabaseInitializer where TContext : DbContext where TConfiguration : DbMigrationsConfiguration, new() { void IDatabaseInitializer.InitializeDatabase(TContext context) { if (context.Database.Exists()) { if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false)) { var migrationInitializer = new MigrateDatabaseToLatestVersion(true); migrationInitializer.InitializeDatabase(context); } } base.InitializeDatabase(context); } } 

Ceci est basé sur les réponses précédentes et sur la propre solution d’OP. Cela devrait également fonctionner avec d’autres fournisseurs, mais j’ai seulement testé avec SQL Server.