Limites d’un fournisseur de base de données EF Core SQLite

Le fournisseur SQLite présente un certain nombre de limitations des migrations. La plupart de ces limitations sont le résultat de limitations dans le moteur de base de données SQLite sous-jacent et ne sont pas spécifiques à EF.

Limitations de la modélisation

La bibliothèque relationnelle commune (partagée par les fournisseurs de bases de données relationnelles EF Core) définit des API pour la modélisation des concepts communs à la plupart des moteurs de base de données relationnelles. Certains de ces concepts ne sont pas pris en charge par le fournisseur SQLite.

Limitations des requêtes

SQLite ne prend pas en charge en mode natif les types de données qui suivent. EF Core peut lire et écrire des valeurs de ces types, et la requête d’égalité (where e.Property == value) est aussi prise en charge. Toutefois, d’autres opérations, comme la comparaison et la commande, nécessitent une évaluation sur le client.

  • DateTimeOffset
  • decimal
  • TimeSpan
  • ulong

Au lieu de DateTimeOffset, nous vous recommandons d’utiliser des valeurs DateTime. Lors de la gestion de plusieurs fuseaux horaires, nous recommandons de convertir les valeurs en UTC avant l’enregistrement, puis de revenir au fuseau horaire approprié.

Le type decimal offre un niveau élevé de précision. Toutefois, si vous n’avez pas besoin de ce niveau de précision, nous vous recommandons d’utiliser double à la place. Vous pouvez utiliser un convertisseur de valeur pour continuer à utiliser decimal dans vos classes.

modelBuilder.Entity<MyEntity>()
    .Property(e => e.DecimalProperty)
    .HasConversion<double>();

Limitations des migrations

Le moteur de base de données SQLite ne prend pas en charge un certain nombre d’opérations de schéma prises en charge par la majorité des autres bases de données relationnelles. Si vous tentez d’appliquer l’une des opérations non prises en charge à une base de données SQLite, une NotSupportedException sera déclenchée.

Une régénération sera tentée pour effectuer certaines opérations. Les régénérations ne sont possibles que pour les artefacts de base de données qui font partie de votre modèle EF Core. Si un artefact de base de données ne fait pas partie du modèle, par exemple s’il a été créé manuellement à l’intérieur d’une migration, une NotSupportedException est toujours déclenchée.

Opération Pris en charge ?
AddCheckConstraint ✔ (reconstruire)
AjouterColonne
AddForeignKey ✔ (reconstruire)
AjouterCléPrimaire ✔ (reconstruire)
AjoutContrainteUnique ✔ (reconstruire)
AlterColumn ✔ (reconstruire)
CréerIndex
CréerTable
SupprimerContrainteDeVérification ✔ (reconstruire)
SupprimerColonne ✔ (reconstruire)
DropForeignKey ✔ (reconstruire)
DropIndex
SupprimerLaCléPrimaire ✔ (reconstruire)
DropTable
SupprimerContrainteUnique ✔ (reconstruire)
RenommerColonne
RenameIndex ✔ (reconstruire)
RenameTable
EnsureSchema ✔ (no-op)
DropSchema ✔ (no-op)
Insérer
Mettre à jour
Supprimer

Solution de contournement des limitations des migrations

Vous pouvez contourner certaines de ces limitations en écrivant manuellement du code dans vos migrations pour effectuer une régénération. Les régénérations de table impliquent la création d’une table, la copie de données dans la nouvelle table, la suppression de l’ancienne table et le changement de nom de la nouvelle table. Vous devrez utiliser la méthode Sql pour effectuer certaines de ces étapes.

Pour plus de détails, consultez Réaliser d’autres types de modifications de schémas de table dans la documentation SQLite.

Limites du script idempotent

Contrairement à d’autres bases de données, SQLite n’inclut pas de langage procédural. Pour cette raison, il n’existe aucun moyen de générer la logique if-then requise par les scripts de migration idempotent.

Si vous connaissez la dernière migration appliquée à une base de données, vous pouvez générer un script de cette migration vers la migration la plus récente.

dotnet ef migrations script CurrentMigration

Sinon, nous vous recommandons d’utiliser dotnet ef database update pour appliquer des migrations. Vous pouvez spécifier le fichier de base de données lors de l’exécution de la commande.

dotnet ef database update --connection "Data Source=My.db"

Protection des migrations concurrentes

EF9 a introduit un mécanisme de verrouillage de migration pour se protéger contre les exécutions de migration simultanées. Contrairement à SQL Server, qui utilise un verrou d'application au niveau de la session (sp_getapplock) qui est automatiquement libéré lorsque la connexion se ferme, SQLite n'a pas de verrous d'application intégrés. EF Core crée à la place une table __EFMigrationsLock et insère une ligne pour acquérir le verrou.

Gestion des verrous abandonnés

Si l’application se termine de façon inattendue (par exemple, si le processus est interrompu pendant la migration), la ligne de verrouillage dans la table __EFMigrationsLock risque de ne pas être nettoyée. Cela empêche toute migration ultérieure de se terminer, car chaque tentative attend indéfiniment que le verrou soit libéré.

Pour résoudre un verrou abandonné, supprimez la __EFMigrationsLock table de la base de données :

DROP TABLE "__EFMigrationsLock";

Vous pouvez également supprimer toutes les lignes de la table :

DELETE FROM "__EFMigrationsLock";

Après avoir désactivé le verrou, les opérations de migration suivantes se poursuivent normalement. La table est recréée automatiquement en fonction des besoins.

Voir aussi