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.
- Schémas
- Séquences
- Jetons de concurrence générés par la base de données (voir la documentation)
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.