Partilhar via


Limitações do provedor de banco de dados SQL EF Core

O provedor SQLite tem várias limitações de migrações. A maioria dessas limitações é resultado de limitações no mecanismo de banco de dados SQLite subjacente e não são específicas do EF.

Limitações de modelagem

A biblioteca relacional comum (compartilhada por provedores de banco de dados relacional EF Core) define APIs para conceitos de modelagem que são comuns à maioria dos mecanismos de banco de dados relacional. Alguns desses conceitos não são suportados pelo provedor SQLite.

Limitações de consulta

O SQLite não suporta nativamente os seguintes tipos de dados. EF Core pode ler e gravar valores desses tipos, e a consulta por igualdade (where e.Property == value) também é suportada. Outras operações, no entanto, como comparação e encomenda exigirão avaliação no cliente.

  • DateTimeOffset
  • decimal
  • TimeSpan
  • ulong

Em vez de DateTimeOffset, recomendamos usar valores DateTime. Ao lidar com vários fusos horários, recomendamos converter os valores em UTC antes de salvar e, em seguida, converter novamente para o fuso horário apropriado.

O tipo decimal fornece um alto nível de precisão. Se você não precisa desse nível de precisão, no entanto, recomendamos usar double em vez disso. Você pode usar um conversor de valor para continuar usando decimal em suas classes.

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

Limitações das migrações

O mecanismo de banco de dados SQLite não suporta várias operações de esquema que são suportadas pela maioria dos outros bancos de dados relacionais. Se você tentar aplicar uma das operações sem suporte a um banco de dados SQLite, uma NotSupportedException será lançada.

Será tentada uma reconstrução para executar determinadas operações. As reconstruções só são possíveis para artefatos de banco de dados que fazem parte do seu modelo EF Core. Se um artefato de banco de dados não fizer parte do modelo - por exemplo, se foi criado manualmente dentro de uma migração - um NotSupportedException ainda será gerado.

Funcionamento Suportado?
AdicionarRestriçãoDeVerificação ✔ (reconstruir)
AdicionarColuna
AddForeignKey ✔ (reconstruir)
AdicionarChavePrimária ✔ (reconstruir)
AdicionarRestriçãoÚnica ✔ (reconstruir)
AlterColumn ✔ (reconstruir)
CriarÍndice
CriarTabela
RemoverRestriçãoDeVerificação ✔ (reconstruir)
DropColumn ✔ (reconstruir)
DropForeignKey ✔ (reconstruir)
DropIndex
DropPrimaryKey ✔ (reconstruir)
DropTable
RemoverRestriçãoÚnica ✔ (reconstruir)
RenomearColuna
RenomearÍndice ✔ (reconstruir)
RenomearTabela
EnsureSchema ✔ (no-op)
DropSchema ✔ (no-op)
Inserir
Atualizar
Suprimir

Soluções para ultrapassar limitações de migrações

Você pode contornar algumas dessas limitações escrevendo manualmente código em suas migrações para executar uma reconstrução. As reconstruções de tabela envolvem a criação de uma nova tabela, a cópia de dados para a nova tabela, a eliminação da tabela antiga e a renomeação da nova tabela. Você precisará usar o método Sql para executar algumas dessas etapas.

Consulte Fazendo outros tipos de alterações de esquema de tabela na documentação do SQLite para obter mais detalhes.

Limitações idempotentes de script

Ao contrário de outros bancos de dados, o SQLite não inclui uma linguagem processual. Por isso, não há como gerar a lógica if-then exigida pelos scripts de migração idempotentes.

Se você souber a última migração aplicada a um banco de dados, poderá gerar um script dessa migração para a migração mais recente.

dotnet ef migrations script CurrentMigration

Caso contrário, recomendamos o uso de dotnet ef database update para aplicar migrações. Você pode especificar o arquivo de banco de dados ao executar o comando.

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

Proteção contra migrações simultâneas

O EF9 introduziu um mecanismo de bloqueio ao executar migrações. Ele visa proteger contra várias execuções de migração acontecendo simultaneamente, pois isso poderia deixar o banco de dados em um estado corrompido. Este é um dos problemas potenciais resultantes da aplicação de migrações em tempo de execução usando o método Migrate (consulte Aplicando migrações para obter mais informações). Para atenuar isso, o EF cria um bloqueio exclusivo no banco de dados antes que qualquer operação de migração seja aplicada.

Infelizmente, o SQLite não tem mecanismo de bloqueio integrado, então o EF Core cria uma tabela separada (__EFMigrationsLock) e a usa para bloqueio. O bloqueio é liberado quando a migração é concluída e o código de propagação termina a execução. No entanto, se, por algum motivo, a migração falhar de forma não recuperável, o bloqueio pode não ser liberado corretamente. Se isso acontecer, migrações consecutivas serão impedidas de executar SQL e, portanto, nunca serão concluídas. Você pode desbloqueá-los manualmente excluindo a tabela __EFMigrationsLock no banco de dados.

Ver também