Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Una vez agregadas las migraciones, deben implementarse y aplicarse a las bases de datos. Hay varias estrategias para hacerlo. Algunas son más adecuadas para entornos de producción, y otras, para el ciclo de vida de desarrollo.
Note
Independientemente de la estrategia de implementación, inspeccione siempre las migraciones generadas y pruébelas antes de aplicarlas a una base de datos de producción. Una migración puede quitar una columna cuando la intención era cambiarle el nombre, o puede producir un error por diversos motivos cuando se aplica a una base de datos.
Elección de una estrategia de implementación
Para la implementación automatizada, use una agrupación de migración. Una agrupación es un artefacto de implementación que se puede generar en CI y que se ejecuta más adelante sin el SDK de .NET, las herramientas de EF Core o el código fuente de la aplicación. Use un script SQL en su lugar cuando se debe revisar, modificar, archivar o entregar a un DBA antes de aplicarlo.
Para el desarrollo local, dotnet ef database update o Update-Database normalmente es la opción más sencilla. Los proyectos aspire deben usar la integración de migraciones de Aspire EF Core para coordinar la ejecución de la migración local y publicar paquetes o scripts.
| Strategy | Uso recomendado | Revisión de SQL antes de la ejecución | Requiere el SDK y el origen en la ejecución | Usa el bloqueo de migración de EF | Ejecuta delegados de propagación de EF |
|---|---|---|---|---|---|
| Script SQL | Implementación controlada por DBA o controlada por revisión | Yes | No | No | No |
| Agrupación de migración | Implementación automatizada | No | No | Yes | Yes |
| Herramientas de línea de comandos de EF | Desarrollo y pruebas locales | No | Yes | Yes | Yes |
| Migración en tiempo de ejecución | Aplicaciones que aceptan inconvenientes de la migración de inicio | No | No | Yes | Yes |
EF Core 9 y versiones posteriores usan el bloqueo de migración. Las operaciones sincrónicas y las herramientas invocan UseSeeding; las operaciones asincrónicas invocan UseAsyncSeeding.
Use una identidad independiente para la implementación que tenga permiso para cambiar el esquema. La identidad usada por la aplicación en tiempo de ejecución normalmente debería tener solo los permisos que la aplicación necesita para leer y escribir datos.
Scripts de SQL
Se recomiendan scripts SQL cuando el proceso de implementación requiere que se inspeccione o cambie sql generado antes de la ejecución. Entre las ventajas de esta estrategia se incluyen las siguientes:
- Los scripts SQL se pueden revisar para obtener precisión. Esto es importante, ya que aplicar cambios de esquema a las bases de datos de producción es una operación potencialmente peligrosa que podría implicar la pérdida de datos.
- En algunos casos, los scripts se pueden ajustar para adaptarse a las necesidades específicas de una base de datos de producción.
- Los scripts SQL se pueden usar junto con una tecnología de implementación e incluso se pueden generar como parte del proceso de CI.
- Los scripts SQL se pueden proporcionar a un DBA y se pueden administrar y archivar por separado.
Uso básico
El siguiente código genera un script SQL de una base de datos en blanco a la migración más reciente:
dotnet ef migrations script
De forma predeterminada, el comando escribe el script en la salida estándar. Use --output (o -o) para crear un artefacto de implementación con un nombre predecible:
dotnet ef migrations script --idempotent --output artifacts/migrations.sql
Con From (To implícito)
El siguiente código genera un script SQL de la migración especificada a la migración más reciente.
dotnet ef migrations script AddNewTables
Con From y To
Lo siguiente genera un script SQL desde la migración from especificada hasta la migración to especificada.
dotnet ef migrations script AddNewTables AddAuditTable
Puede usar un valor from que sea más reciente que el valor to para generar un script de reversión.
Warning
Tome nota de los posibles escenarios de pérdida de datos.
La generación de scripts acepta los dos argumentos siguientes para indicar qué intervalo de migraciones debe generarse:
- La migración from debe ser la última migración aplicada a la base de datos antes de ejecutar el script. Si no se han aplicado migraciones, especifique
0(es el valor predeterminado). - La migración to debe ser la última migración que se va a aplicar a la base de datos después de ejecutar el script. El valor predeterminado es la última migración del proyecto.
Los scripts de migración actualizan una base de datos existente. Aprovisione la propia base de datos a través del proceso de implementación de infraestructura o administración de bases de datos antes de aplicar el script. La creación de bases de datos normalmente requiere una conexión diferente, permisos elevados y configuración específica del proveedor.
Scripts SQL idempotentes
Los scripts SQL generados en la sección anterior solo se pueden aplicar para cambiar el esquema de una migración a otra. Es su responsabilidad aplicar el script adecuadamente y solo a las bases de datos con el estado de migración correcto. EF Core también admite la generación de scripts idempotentes, que comprueban internamente qué migraciones se han aplicado ya (a través de la tabla del historial de migraciones) y solo aplican las que faltan. Esto es útil si no sabe exactamente cuál ha sido la última migración aplicada a la base de datos o si va a hacer una implementación en varias bases de datos que pueden estar en migraciones diferentes.
La compatibilidad con scripts idempotentes depende del proveedor de base de datos. Por ejemplo, SQLite no admite actualmente la generación de scripts de migración idempotentes.
El siguiente código genera migraciones idempotentes:
dotnet ef migrations script --idempotent
Herramientas de línea de comandos
Las herramientas de línea de comandos de EF se pueden usar para aplicar migraciones a una base de datos. Aunque es productivo para el desarrollo y las pruebas de migraciones en modo local, este enfoque no es ideal para administrar bases de datos de producción:
- La herramienta aplica directamente los comandos SQL, sin dar al desarrollador la oportunidad de inspeccionarlos o modificarlos. Esto puede ser peligroso en un entorno de producción.
- El SDK de .NET y la herramienta EF deben instalarse en servidores de producción y requiere el código fuente del proyecto.
El siguiente código actualiza la base de datos a la migración más reciente:
dotnet ef database update
El siguiente código actualiza la base de datos a una migración determinada:
dotnet ef database update AddNewTables
Tenga en cuenta que esto también se puede usar para revertir a una migración anterior.
Warning
Tome nota de los posibles escenarios de pérdida de datos.
Para obtener más información sobre cómo aplicar migraciones con las herramientas de línea de comandos, consulte la referencia de las herramientas de EF Core.
Entorno y configuración
Las herramientas ejecutan código de aplicación para construir .DbContext Por lo tanto, la selección del proveedor, las cadenas de conexión y la configuración del modelo pueden depender del entorno de la aplicación. Las herramientas en tiempo de diseño de EF Core usan el Development entorno cuando no ASPNETCORE_ENVIRONMENT se establece ni DOTNET_ENVIRONMENT .
Establezca explícitamente el entorno al generar un artefacto de implementación y al ejecutar una agrupación. Por ejemplo, en PowerShell:
$env:ASPNETCORE_ENVIRONMENT = 'Production'
dotnet ef migrations bundle --output artifacts\efbundle.exe
$env:ASPNETCORE_ENVIRONMENT = 'Production'
.\efbundle.exe --connection $env:DEPLOYMENT_CONNECTION_STRING
O bien, en un shell compatible con POSIX:
ASPNETCORE_ENVIRONMENT=Production \
dotnet ef migrations bundle --output artifacts/efbundle
ASPNETCORE_ENVIRONMENT=Production \
./efbundle --connection "$DEPLOYMENT_CONNECTION_STRING"
Esto también impide que una agrupación cargue secretos de usuario de desarrollo de forma inesperada. Dotnet/efcore#36188 realiza un seguimiento de un entorno predeterminado más seguro para las agrupaciones. Dotnet/efcore#11950 realiza un seguimiento de la selección del entorno en la experiencia de publicación de Visual Studio.
No almacene cadenas de conexión de producción en el control de código fuente ni insertelas en la agrupación. Proporcione la conexión de implementación desde el almacén de secretos del sistema de implementación. La identidad de implementación debe tener permisos de esquema; Normalmente, la identidad de aplicación normal no debería.
Bundles
Los paquetes de migración son archivos ejecutables únicos que se pueden usar para aplicar migraciones a una base de datos. Solucionan algunas de las deficiencias de los scripts SQL y las herramientas de línea de comandos:
- La ejecución de scripts SQL requiere herramientas adicionales.
- El control de transacciones y el comportamiento de continuar en caso de error de estas herramientas son incoherentes y a veces inesperados. Esto puede dejar una base de datos en un estado indefinido si se produce un error al aplicar migraciones.
- Las agrupaciones se pueden generar como parte del proceso de CI y se pueden ejecutar fácilmente más adelante como parte del proceso de implementación.
- Los conjuntos se pueden ejecutar sin instalar el SDK de .NET o la herramienta EF (o incluso el entorno de ejecución de .NET, cuando están independientes) y no requieren el código fuente del proyecto.
- Los conjuntos usan el bloqueo de migración de EF Core y ejecutan lógica configurada
UseSeeding.
A diferencia de un script SQL, una agrupación no proporciona actualmente una manera de inspeccionar sql que ejecutará o enumerará las migraciones que contiene. Si la implementación requiere una revisión de SQL, genere un script en su lugar. Dotnet/efcore#25872 realiza un seguimiento de las mejoras de inspección de agrupación.
El siguiente genera un paquete:
dotnet ef migrations bundle --output artifacts/efbundle
El siguiente código genera un paquete autónomo para Linux.
dotnet ef migrations bundle --self-contained --target-runtime linux-x64 --output artifacts/efbundle
Para obtener más información sobre la creación de agrupaciones, consulte la referencia de las herramientas de EF Core.
efbundle
El archivo ejecutable resultante se denomina efbundle de forma predeterminada. Se puede usar para actualizar la base de datos a la migración más reciente. Esto equivale a ejecutar dotnet ef database update o Update-Database.
Arguments:
| Argument | Description |
|---|---|
<MIGRATION> |
La migración de destino. Si es "0", todas las migraciones serán revertidas. Establece el valor predeterminado a la última migración. |
Options:
| Option | Short | Description |
|---|---|---|
--connection <CONNECTION> |
La cadena de conexión de la base de datos. El valor predeterminado es el especificado en AddDbContext o OnConfiguring. | |
--verbose |
-v |
Mostrar resultado detallado. |
--no-color |
No colorees la salida. | |
--prefix-output |
Agregar nivel como prefijo a la salida. |
En el ejemplo siguiente se aplican migraciones a una instancia de SQL Server local mediante el nombre de usuario y las credenciales especificados:
.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password={;'$Credential;'here'}'
Para revertir la base de datos, pase la migración que debe permanecer aplicada. Pasar 0 revierte todas las migraciones:
.\efbundle.exe PreviousMigration --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;Integrated Security=True'
.\efbundle.exe 0 --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;Integrated Security=True'
Warning
Una reversión ejecuta las Down operaciones de cada migración más reciente que el destino y puede provocar la pérdida de datos. Revise y pruebe el comportamiento de reversión antes de usarlo en los datos de producción.
El código de propagación configurado se ejecuta después de una degradación. Debe tolerar el esquema de la migración de destino, incluido un esquema de aplicación que falta cuando el destino es 0.
Warning
Si la configuración de contexto lee appsettings.json, copie los archivos de configuración necesarios junto con la agrupación. Los archivos de configuración se resuelven desde el directorio de ejecución del lote. No coloque secretos de producción en estos archivos; proporcionarlos a través de un origen de configuración seguro o la --connection opción .
Contenedores y trabajos de implementación
Genere la agrupación durante la compilación y ejecútela como un trabajo de implementación único después de que la base de datos esté en buen estado. No instale el SDK ni ejecute dotnet ef en la imagen de la aplicación y no realice migraciones de todas las réplicas de aplicación que ejecuten migraciones desde su punto de entrada. Configure la plataforma de implementación para no reiniciar el contenedor de migración después de que se cierre correctamente.
En el caso de las aplicaciones Aspire, AddEFMigrations puede coordinar las migraciones durante el desarrollo local. Durante la publicación, PublishAsMigrationBundle puede emitir una agrupación o una imagen de contenedor y PublishAsMigrationScript puede emitir un script SQL. Consulte Aplicación de migraciones de EF Core en Aspire para la configuración de trabajos de un solo uso para Azure Container Apps, Docker Compose y Kubernetes.
En el ejemplo de agrupación de migración se muestran dos migraciones de SQLite, propagación idempotente, aplicación de reenvío y propagación segura para reversión.
Ejemplo de agrupación de migraciones
Una agrupación necesita que se incluyan migraciones. Estas migraciones se crean usando dotnet ef migrations add como se explica en Creación de la primera migración. Una vez que tenga las migraciones listas para implementarse, cree un paquete mediante dotnet ef migrations bundle. Por ejemplo:
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>
La salida es un ejecutable adecuado para el sistema operativo de destino. En mi caso, esto es Windows x64, por lo que obtengo un efbundle.exe colocado en mi carpeta local. Al ejecutar este ejecutable se aplican las migraciones que contiene:
PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903083845_MyMigration'.
Done.
PS C:\local\AllTogetherNow\SixOh>
Al igual que con dotnet ef database update o Update-Database, las migraciones se aplican a la base de datos solo si aún no se han aplicado. Por ejemplo, la ejecución de la misma agrupación de nuevo no hace nada, ya que no hay migraciones nuevas que aplicar:
PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
No migrations were applied. The database is already up to date.
Done.
PS C:\local\AllTogetherNow\SixOh>
Pero si se realizan cambios en el modelo y se generan más migraciones con dotnet ef migrations add, se pueden agrupar en un nuevo ejecutable listo para su aplicación. Por ejemplo:
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add SecondMigration
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add Number3
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle --force
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>
Tip
Se puede usar la opción --force para sobrescribir la agrupación actual con una nueva.
La ejecución de esta nueva agrupación aplica estas dos migraciones nuevas a la base de datos:
PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>
De forma predeterminada, el paquete utiliza la cadena de conexión de la base de datos de la configuración de la aplicación. Sin embargo, se puede migrar una base de datos diferente pasando el cadena de conexión en la línea de comandos. Por ejemplo:
PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe --connection "Data Source=(LocalDb)\MSSQLLocalDB;Database=SixOhProduction"
Applying migration '20210903083845_MyMigration'.
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>
Note
Esta vez, se han aplicado las tres migraciones, ya que aún no se había aplicado ninguna de ellas a la base de datos de producción.
Aplicar migraciones en tiempo de ejecución
Es posible que la propia aplicación aplique migraciones mediante programación, normalmente durante el inicio. EF Core 9 y versiones posteriores protegen la ejecución de la migración con un bloqueo en toda la base de datos, por lo que esto puede ser aceptable para las aplicaciones que prefieren una implementación sencilla y pueden tolerar el comportamiento de la migración de inicio. Todavía se prefiere un paso de implementación de migración independiente cuando se revisan, las credenciales con privilegios mínimos, el lanzamiento coordinado o la alta disponibilidad es importante.
Tenga en cuenta los siguientes inconvenientes:
- Para versiones de EF anteriores a la 9, si se están ejecutando varias instancias de su aplicación, ambas aplicaciones podrían intentar aplicar la migración simultáneamente y fallar (o peor aún, provocar la corrupción de los datos).
- De forma similar, si una aplicación accede a la base de datos mientras otra aplicación la migra, esto puede provocar problemas graves.
- La aplicación debe tener acceso con privilegios elevados para modificar el esquema de la base de datos. En general, se recomienda limitar los permisos de las aplicaciones para las bases de datos en producción.
- Es importante poder revertir una migración aplicada en el caso de que surja un problema. Las otras estrategias permiten hacer esto fácilmente y sin necesidad de configurar nada.
- El programa aplica directamente los comandos SQL, sin dar al desarrollador la oportunidad de inspeccionarlos o modificarlos. Esto puede ser peligroso en un entorno de producción.
Para aplicar migraciones mediante programación, llame a context.Database.MigrateAsync(). Por ejemplo, una aplicación de ASP.NET típica puede hacer lo siguiente:
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
await db.Database.MigrateAsync();
}
host.Run();
}
Tenga en cuenta que MigrateAsync() se basa en el servicio IMigrator, que se puede usar para escenarios más avanzados. Use myDbContext.GetInfrastructure().GetService<IMigrator>() para acceder a él.
Warning
- Piénselo detenidamente antes de usar este enfoque en producción. Se prefiere una agrupación de migración para la automatización o un script SQL cuando se requieren revisión y aprobación.
- No llame a
EnsureCreatedAsync()antes deMigrateAsync().EnsureCreatedAsync()omite las migraciones para crear el esquema, lo que hace queMigrateAsync()falle.
Bloqueo de migración
A partir de EF Core 9, MigrateAsync y Migrate adquieren automáticamente un bloqueo de toda la base de datos antes de aplicar las migraciones. Esto protege contra daños en la base de datos que podrían resultar de varias instancias de aplicación que ejecutan migraciones simultáneamente, que es un escenario común al aplicar migraciones en tiempo de ejecución. El bloqueo se mantiene durante toda la ejecución de la migración, incluyendo cualquier código de siembra, y se libera automáticamente cuando la operación completa.
El bloqueo de migración se aplica cuando se aplican migraciones mediante cualquiera de los métodos siguientes:
-
dotnet ef database update(CLI de .NET) -
Update-Database(Consola del Administrador de Paquetes) - Agrupaciones de migración
- MigrateAsync y Migrate (migración en tiempo de ejecución)
Los scripts SQL no se ven afectados por el bloqueo de migración, ya que se aplican fuera de EF Core.
Note
A partir de EF Core 9, al llamar a Migrate() o MigrateAsync() se producirá una excepción cuando el modelo tenga cambios pendientes en comparación con la última migración (identificador RelationalEventId.PendingModelChangesWarningde evento de advertencia). Para detectar esta condición antes del despliegue, use el comando dotnet ef migrations has-pending-model-changes en su pipeline de CI/CD. La advertencia puede suprimirse mediante ConfigureWarnings (omitiendo RelationalEventId.PendingModelChangesWarning) si es necesario, pero por lo general no se recomienda en entornos de producción. Consulte la nota sobre cambios importantes para obtener más información.
Warning
El mecanismo de bloqueo varía significativamente entre los proveedores de bases de datos y puede implicar problemas específicos del proveedor. Por ejemplo, el proveedor de SQLite usa una tabla de bloqueo que se puede abandonar si el proceso finaliza inesperadamente. Consulte siempre la documentación de su proveedor para obtener más información.
Limitaciones
- No se admite el ajuste MigrateAsync en una transacción explícita. Consulte Excepción que se produce al aplicar migraciones en una transacción explícita para obtener más información.
- En SQLite, los bloqueos de migración abandonados pueden bloquear las migraciones posteriores.