SQLite EF Core-Datenbank-Anbieter-Einschränkungen

Der SQLite-Anbieter hat eine Reihe von Migrationseinschränkungen. Die meisten dieser Einschränkungen ergeben sich aus Einschränkungen im zugrunde liegenden SQLite-Datenbankmodul und sind nicht spezifisch für EF.

Modellierungseinschränkungen

Die gemeinsame relationale Bibliothek (die von den Anbietern relationaler Datenbanken von Entity Framework gemeinsam genutzt wird) definiert APIs für Modellierungskonzepte, die den meisten relationalen Datenbank-Engines gemeinsam sind. Einige dieser Konzepte werden vom SQLite-Anbieter nicht unterstützt.

Abfrageeinschränkungen

SQLite unterstützt die folgenden Datentypen nicht nativ. EF Core kann Werte dieser Typen lesen und schreiben, und die Abfrage nach Gleichheit (where e.Property == value) wird ebenfalls unterstützt. Andere Vorgänge, z. B. Vergleich und Sortierung, erfordern jedoch eine Auswertung auf dem Client.

  • DateTimeOffset
  • Decimal
  • TimeSpan
  • UInt64

Anstelle von DateTimeOffset empfehlen wir die Verwendung von DateTime-Werten. Wenn Sie mit mehreren Zeitzonen arbeiten, empfehlen wir Ihnen, die Werte vor dem Speichern in UTC zu konvertieren und dann in die entsprechende Zeitzone zurück zu konvertieren.

Der Decimal Typ bietet eine hohe Genauigkeit. Wenn Sie diese Präzision jedoch nicht benötigen, empfehlen wir Ihnen, die doppelte Zahl zu verwenden. Sie können einen Wertkonverter verwenden, um die Dezimalzahl in Ihren Klassen fortzusetzen.

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

Migrationseinschränkungen

Das SQLite-Datenbankmodul unterstützt keine Anzahl von Schemavorgängen, die von den meisten anderen relationalen Datenbanken unterstützt werden. Wenn Sie versuchen, einen der nicht unterstützten Vorgänge auf eine SQLite-Datenbank anzuwenden, wird ein NotSupportedException ausgelöst.

Es wird versucht, eine Neuerstellung durchzuführen, um bestimmte Vorgänge auszuführen. Neuerstellungen sind nur für Datenbankartefakte möglich, die Teil Ihres EF Core-Modells sind. Wenn ein Datenbank-Artefakt nicht Teil des Modells ist – zum Beispiel, wenn es manuell im Rahmen einer Migration erstellt wurde –, wird trotzdem eine Meldung NotSupportedException ausgegeben.

Vorgang Unterstützt?
AddCheckConstraint ✔ (rebuild)
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)
„Insert“
Aktualisieren
Entf

Migrationseinschränkungen Problemumgehung

Sie können einige dieser Einschränkungen umgehen, indem Sie manuell Code in Ihre Migrationen schreiben, um einen Neuaufbau durchzuführen. Um eine Tabelle neu zu erstellen, müssen Sie eine neue Tabelle erstellen, die Daten in die neue Tabelle kopieren, die alte Tabelle löschen und die neue Tabelle umbenennen. Sie müssen die Sql(string)-Methode verwenden, um einige dieser Schritte auszuführen.

Weitere Informationen finden Sie unter Vornehmen anderer Arten von Tabellenschemaänderungen in der SQLite-Dokumentation.

Einschränkungen von Idempotent-Skripts

Im Gegensatz zu anderen Datenbanken enthält SQLite keine prozedurale Sprache. Aus diesem Grund gibt es keine Möglichkeit, die if-then-Logik zu generieren, die von den idempotenten Migrationsskripts benötigt wird.

Wenn Sie wissen, dass die letzte Migration auf eine Datenbank angewendet wurde, können Sie ein Skript aus dieser Migration zur neuesten Migration generieren.

dotnet ef migrations script CurrentMigration

Andernfalls wird empfohlen, dotnet ef database update zum Anwenden von Migrationen zu verwenden. Sie können die Datenbankdatei beim Ausführen des Befehls angeben.

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

Schutz vor gleichzeitigen Migrationen

EF9 hat einen Sperrmechanismus bei der Ausführung von Migrationen eingeführt. Er dient dazu, die gleichzeitige Ausführung mehrerer Migrationen zu verhindern, da dies die Datenbank beschädigen kann. Dies ist eines der potenziellen Probleme, die sich ergeben, wenn Migrationen zur Laufzeit mithilfe der DbContext.Database.Migrate()-Methode angewendet werden. (Weitere Informationen finden Sie unter Anwenden von Migrationen.) Um dies zu vermeiden, erstellt EF eine exklusive Sperre für die Datenbank, bevor Migrationsvorgänge angewendet werden.

Leider verfügt SQLite über keinen integrierten Sperrmechanismus. Daher erstellt EF eine separate Tabelle (__EFMigrationsLock) und verwendet sie zum Sperren. Die Sperre wird aufgehoben, wenn die Migration abgeschlossen ist und die Ausführung des Seedingcodes beendet wird. Falls bei der Migration allerdings aus irgendeinem Grund ein nicht behebbarer Fehler auftritt, wird die Sperre möglicherweise nicht ordnungsgemäß aufgehoben. In diesem Fall werden nachfolgende Migrationen an der Ausführung von SQL-Code gehindert und können somit nicht abgeschlossen werden. Sie können die Blockierung manuell aufheben, indem Sie die Tabelle __EFMigrationsLock in der Datenbank löschen.

Siehe auch