c# - reconoce - noticias diarios sobre migraciones internacionales
¿Qué archivos me falta si ejecuto migraciones desde una aplicación de consola? (1)
Con Entity Framework 6 y una base de datos PostgreSQL más conexión que funciona estoy tratando de ejecutar los comandos Add-Migration
y Update-Database
y crear un script de actualización a través de una aplicación de consola. Es posible ejecutar los comandos desde una consola, ya que son "envoltorios delgados alrededor de una API", consulte esta respuesta SO para el ejemplo que utilicé.
La creación de migraciones funciona, se crean tres archivos regulares, a saber:
Initial.cs
Initial.Designer.cs
Initial.resx
Aquí está la aplicación de consola que no funciona para Update-Database
.
public static void Main()
{
// Specify the name of the database migration
// Note: make sure to create a new name for each new migration and prefix with
const string MIGRATION_NAME = "Initial";
// END USER INPUT
// Get executing path from which the location of the Update_Scripts and new
// Migrations can be determined.
var executingPath = AppDomain.CurrentDomain.BaseDirectory;
// Write to database (PowerShell: Update-Database)
var config = new Configuration();
var migrator = new DbMigrator(config);
migrator.Update(); // <= HERE IT CRASHES!
// Now create the PostgreSQL update script.
var scriptor = new MigratorScriptingDecorator (migrator);
string script = scriptor.ScriptUpdate (sourceMigration: null, targetMigration: null);
var updateScriptPath = Regex.Replace (executingPath, "Zk.Migrations/.*",
"Zk/App_Data/Update_Scripts");
File.WriteAllText (updateScriptPath + MIGRATION_NAME + ".postgresql", script);
Console.WriteLine ("Update script {0} written to App_Data/Update_Scripts folder", MIGRATION_NAME);
}
Aquí la clase de Configuration
ve de la siguiente manera:
public class Configuration : DbMigrationsConfiguration<ZkContext>
{
public Configuration ()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("Npgsql", new PostgreSqlMigrationSqlGenerator());
}
}
Donde la clase PostgreSqlMigrationSqlGenerator
proviene de este repositorio de GitHub .
Cuando trato de ejecutar la parte de la base de datos de actualización que se encuentra arriba, la aplicación de la consola se bloquea en migrator.Update();
. Esta es la excepción:
No se pudieron encontrar recursos apropiados para la cultura especificada o la cultura neutral. Asegúrese de que "Zk.Migrations.Initial.resources" esté incrustado o vinculado correctamente en el ensamblado "Zk.Migrations" en tiempo de compilación, o que todos los ensamblajes satelitales requeridos sean cargables y estén completamente firmados.
Y aquí está el rastro de la pila:
System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists (mustSucceedToKeepDatabase =
{System.Action}) en System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists
(mustSucceedToKeepDatabase = {System.Action}) en
System.Data.Entity.Migrations.DbMigrator.Update (targetMigration = (null)) en
System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update () en
Zk.Migrations.MigrationsTool.Main () en /home/erwin/zaaikalender/Zk.Migrations
/MigrationsTool.cs:78
No sé cómo proporcionar los recursos adecuados y lograr que el script funcione. ¿Debo ejecutar Enable-Migrations
primero y, en caso afirmativo, cómo? ¡Espero que alguien me pueda ayudar! Gracias.
Hay dos cosas que se deben hacer para que la aplicación de la consola funcione para agregar migraciones de primer código, crear una secuencia de comandos y actualizar la base de datos:
- Dale a los
.cs.
, los archivos.resx
y.Designer.cs
que se crean al agregar una migración con el mismo nombre que el nombre de andamio de migración sin la migración deMigrationId
preprended. De lo contrario, los archivos no podrían ser encontrados. - Haga clic con el botón derecho en el archivo
.resx
recursos y seleccione BuildAction "EmbeddedResource", de lo contrario, los recursos no se pueden encontrar.
Script de trabajo completo de la aplicación de la consola (que usa PostgreSqlMigrationSqlGenerator ):
/// <summary>
/// Class used to generate the code migrations and SQL script based on the Models and update the database.
/// (I.e., runs PowerShell''s Add-Migration and Update-Database, and creates a PostgreSQL script.)
/// See: http://.com/questions/20374783/enable-entity-framework-migrations-in-mono#20382226
///
/// Usage: run by setting Zk.Migrations as Startup project and pressing play.
///
/// Classes of namespace EntityFramework.PostgreSql obtained from:
/// https://github.com/darionato/PostgreSqlMigrationSqlGenerator. License is included.
/// </summary>
class MigrationsTool
{
/// <summary>
/// The entry point of the program, where the program control starts and ends.
/// </summary>
public static void Main()
{
// USER INPUT /////////////////////////////////////////////////////////////////////////////////
// Always first create a new database migration with DatabaseStep.ADD_MIGRATION,
// and include the created files in the project and set resource file to EmbeddedResource.
// After creating a migration run UPDATE_DATABASE to update the database.
const DatabaseStep step = DatabaseStep.UPDATE_DATABASE;
// Specify the name of the database migration in case of ADD-MIGRATION.
// Note: Make sure to create a new name for each new migration.
// After creating migration include the files in the folder by right clicking on
// Zk.Migrations and selecting "Add files from folder". Then add the .cs, .resx and
// .Designer.cs files with the name specified below.
// Last but not least set the .resx file''s build action to EmbeddedResource by right
// clicking on it.
// Make sure that the Setup.postgresql script has run manually to create the database user.
const string MIGRATION_NAME = "CalendarAndUser";
// END USER INPUT /////////////////////////////////////////////////////////////////////////////
// Get executing path from which the location of the Update_Scripts and new Migrations can be determined.
var executingPath = AppDomain.CurrentDomain.BaseDirectory;
// Add a new migration (PowerShell: Add-Migration)
if (step == DatabaseStep.ADD_MIGRATION) {
// Initialize the wrapper classes around the Entity Framework PowerShell API.
var config = new Configuration();
var scaffolder = new MigrationScaffolder(config);
var migration = scaffolder.Scaffold(MIGRATION_NAME);
// Place migration code in main project "Migrations" folder and migration scripts in "App_Data"
var migrationsPath = Regex.Replace(executingPath, "bin/.*", "");
// Write migrations
File.WriteAllText (migrationsPath + MIGRATION_NAME + ".cs", migration.UserCode);
File.WriteAllText (migrationsPath + MIGRATION_NAME + ".Designer.cs", migration.DesignerCode);
using (var writer = new ResXResourceWriter (migrationsPath + MIGRATION_NAME + ".resx"))
{
foreach (var resource in migration.Resources)
{
writer.AddResource(resource.Key, resource.Value);
}
}
Console.WriteLine("EF code migration {0} written to Migrations folder.../n/n" +
"Next step is to include the .cs, .resx and .Designer.cs file in the project" +
"by right clicking on the project and selecting " +
"/"Add files from folder./"/n" +
"Then right click on {0}.resx and set build action to /"EmbeddedResource/""
, migration.MigrationId);
}
else if (step == DatabaseStep.CREATE_SCRIPT)
{
var config = new Configuration();
var migrator = new DbMigrator(config);
var scriptor = new MigratorScriptingDecorator(migrator);
// Determine name of the previous run migration if exists.
string lastMigration = migrator.GetDatabaseMigrations().LastOrDefault();
// Get the script
string script = scriptor.ScriptUpdate(sourceMigration: lastMigration, targetMigration: MIGRATION_NAME);
// Create the PostgreSQL update script based on last migration on database and
// current migration.
string formattedScript = string.Format
("/* * * * * * * * * * * * * * * * * * * * * * */n" +
" */n" +
" * Migration:/t/t{0}/n */n" +
" * Date and time:/t{1}/n" +
" */n" +
" * * * * * * * * * * * * * * * * * * * * * * *//n/n" +
"{2}",
MIGRATION_NAME,
DateTime.Now,
script);
// Write string to file in Migrations folder of main project
var updateScriptPath = Regex.Replace(executingPath, "Zk.Migrations/.*", "Zk/App_Data/Migrations/");
File.WriteAllText(updateScriptPath + MIGRATION_NAME + ".postgresql", formattedScript);
Console.WriteLine("Update script {0}.postgresql written to Zk/App_Data/Migrations folder./n" +
"Please include the script by right clicking on the folder and selecting " +
"/"Add files to folder/"," +
"/nIt is recommended to prefix the filename with the current datetime.",
MIGRATION_NAME);
}
// If a new migration is created the database can be updated. (PowerShell: Update-Database)
else if (step == DatabaseStep.UPDATE_DATABASE)
{
var config = new Configuration();
var migrator = new DbMigrator(config);
// Write to database
migrator.Update();
// Show which migrations were applied.
var migrationNames = string.Join(", ", migrator.GetDatabaseMigrations().ToArray().First());
Console.WriteLine("Applied migration {0} to database.", migrationNames);
}
}
/// <summary>
/// Enumeration for specifying the step in the migration.
/// </summary>
private enum DatabaseStep
{
ADD_MIGRATION,
CREATE_SCRIPT,
UPDATE_DATABASE
}
}