Compartir a través de


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.

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.

Consulte también