Partage via


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 Entity Framework) définit des API pour la modélisation des concepts communs à la plupart des moteurs de base de donnée relationnelle. 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 l’interrogation de l’égalité (where e.Property == value) est également prise en charge. Toutefois, d’autres opérations, comme la comparaison et la commande, nécessitent une évaluation sur le client.

  • DateTimeOffset
  • Décimal
  • TimeSpan
  • UInt64

Nous recommandons d’utiliser des valeurs DateTime plutôt que DateTimeOffset. 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 valeurs 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 levé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 encore levée.

Opération Pris en charge ?
AddCheckConstraint ✔ (régénéré)
AddColumn
AddForeignKey ✔ (régénéré)
AddPrimaryKey ✔ (régénéré)
AddUniqueConstraint ✔ (régénéré)
AlterColumn ✔ (régénéré)
CreateIndex
CreateTable
DropCheckConstraint ✔ (régénéré)
DropColumn ✔ (régénéré)
DropForeignKey ✔ (régénéré)
DROP index
DropPrimaryKey ✔ (régénéré)
DropTable
DropUniqueConstraint ✔ (régénéré)
RenameColumn
RenameIndex ✔ (régénéré)
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(string) 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.

Limitations 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 lors de l’exécution des migrations. Il vise à protéger contre plusieurs exécutions de migrations se produisant simultanément, ce qui pourrait laisser la base de données dans un état corrompu. C’est l’un des problèmes potentiels résultant de l’application des migrations à l’exécution en utilisant la méthode DbContext.Database.Migrate() (voir Application des migrations pour plus d’informations). Pour atténuer ce risque, EF crée un verrou exclusif sur la base de données avant que toute opération de migration ne soit appliquée.

Malheureusement, SQLite n’a pas de mécanisme de verrouillage intégré, donc EF crée une table distincte (__EFMigrationsLock) et l’utilise pour le verrouillage. Le verrou est libéré lorsque la migration se termine et que le code d’amorçage a terminé son exécution. Cependant, si pour une raison quelconque la migration échoue de manière non récupérable, le verrou peut ne pas être correctement libéré. Si cela se produit, les migrations suivantes seront bloquées de l’exécution des commandes SQL et ne se termineront donc jamais. Vous pouvez les débloquer manuellement en supprimant la table __EFMigrationsLock dans la base de données.

Voir aussi