Limitaciones del proveedor de base de datos SQLite para EF Core
El proveedor de SQLite tiene varias limitaciones de migraciones. La mayoría de estas limitaciones son el resultado de las limitaciones del motor de base de datos de SQLite subyacente y no son específicas de EF.
Limitaciones del modelado
La biblioteca relacional común (compartida por proveedores de bases de datos relacionales de Entity Framework) define las API para los conceptos de modelado que son comunes a la mayoría de los motores de base de datos relacionales. El proveedor de SQLite no admite un par de estos conceptos.
- Esquemas
- Secuencias
- Tokens de simultaneidad generados por la base de datos (consulte la documentación)
Limitaciones de las consultas
SQLite no admite de forma nativa los siguientes tipos de datos. EF Core puede leer y escribir valores de estos tipos y también se admite la consulta de igualdad (where e.Property == value
). Sin embargo, otras operaciones, como la comparación y la ordenación, requerirán evaluación en el cliente.
- DateTimeOffset
- Decimal
- TimeSpan
- UInt64
En lugar de DateTimeOffset
, se recomienda usar valores DateTime. Al controlar varias zonas horarias, se recomienda convertir los valores a UTC antes de guardar y, a continuación, volver a convertir a la zona horaria adecuada.
El tipo Decimal
proporciona un alto nivel de precisión. Sin embargo, si no necesita ese nivel de precisión, se recomienda usar double en su lugar. Puede usar un convertidor de valores para seguir usando decimales en las clases.
modelBuilder.Entity<MyEntity>()
.Property(e => e.DecimalProperty)
.HasConversion<double>();
Limitaciones de las migraciones
El motor de base de datos de SQLite no admite una serie de operaciones de esquema compatibles con la mayoría de otras bases de datos relacionales. Si intenta aplicar una de las operaciones no admitidas a una base de datos de SQLite, se producirá una excepción NotSupportedException
.
Se intentará volver a generar para realizar determinadas operaciones. Las recompilaciones solo son posibles para los artefactos de base de datos que forman parte del modelo de EF Core. Si un artefacto de base de datos no forma parte del modelo, por ejemplo, si se creó manualmente dentro de una migración, se sigue produciendo una excepción NotSupportedException
.
Operación | ¿Compatible? |
---|---|
AddCheckConstraint | ✔ (rebuild) |
1 = ADDCOLUMN | ✔ |
AddForeignKey | ✔ (rebuild) |
AddPrimaryKey | ✔ (rebuild) |
AddUniqueConstraint | ✔ (rebuild) |
AlterColumn | ✔ (rebuild) |
CreateIndex | ✔ |
CreateTable | ✔ |
DropCheckConstraint | ✔ (rebuild) |
DropColumn | ✔ (rebuild) |
DropForeignKey | ✔ (rebuild) |
DropIndex | ✔ |
DropPrimaryKey | ✔ (rebuild) |
DropTable | ✔ |
DropUniqueConstraint | ✔ (rebuild) |
RenameColumn | ✔ |
RenameIndex | ✔ (rebuild) |
RenameTable | ✔ |
EnsureSchema | ✔ (no-op) |
DropSchema | ✔ (no-op) |
Insertar | ✔ |
Actualizar | ✔ |
Eliminar | ✔ |
Solución a las limitaciones de las migraciones
Puede solucionar algunas de estas limitaciones escribiendo manualmente código en las migraciones para realizar una recompilación. Las recompilaciones de tablas implican crear una nueva tabla, copiar datos en la nueva tabla, quitar la tabla antigua y cambiar el nombre de la nueva tabla. Deberá usar el método Sql(string)
para realizar algunos de estos pasos.
Consulte Realizar otros tipos de cambios de esquema de tabla en la documentación de SQLite para obtener más detalles.
Limitaciones del script Idempotent
A diferencia de otras bases de datos, SQLite no incluye un lenguaje de procedimientos. Debido a esto, no hay ninguna manera de generar la lógica if-then requerida por los scripts de migración idempotentes.
Si conoce la última migración aplicada a una base de datos, puede generar un script de esa migración a la migración más reciente.
dotnet ef migrations script CurrentMigration
De lo contrario, se recomienda usar dotnet ef database update
para aplicar migraciones. Puede especificar el archivo de base de datos al ejecutar el comando.
dotnet ef database update --connection "Data Source=My.db"
Protección de migraciones simultáneas
EF9 introdujo un mecanismo de bloqueo al ejecutar migraciones. Su objetivo es proteger contra múltiples ejecuciones de migración que ocurren simultáneamente, ya que podría dejar la base de datos en un estado corrupto. Este es uno de los posibles problemas derivados de la aplicación de migraciones en tiempo de ejecución mediante el método DbContext.Database.Migrate()
(para más información, consulte Aplicación de migraciones). Para evitarlo, EF crea un bloqueo exclusivo en la base de datos antes de aplicar cualquier operación de migración.
Desafortunadamente, SQLite no tiene un mecanismo de bloqueo incorporado, por lo que EF crea una tabla (__EFMigrationsLock
) separada y la utiliza para el bloqueo. El bloqueo se libera cuando la migración finaliza y el código de siembra termina de ejecutarse. Sin embargo, si por alguna razón la migración falla de forma irrecuperable, puede que el bloqueo no se libere correctamente. Si esto ocurre, las migraciones consecutivas quedarán bloqueadas para ejecutar SQL y, por tanto, nunca se completarán. Puede desbloquearlas manualmente borrando la tabla __EFMigrationsLock
en la base de datos.