EF Core - SQLServer迁移适用于SQLite吗?

4

我有一个简单的项目,最初使用SQL Server作为后端,采用EF Core和Code-First方法(遵循此教程:https://learn.microsoft.com/en-us/ef/core/get-started/aspnetcore/new-db)。

现在我想将实现切换到SQLite。我认为我可以只从SQL Server运行初始迁移以创建数据库,然后将其应用于SQLite。但似乎并不正确:例如,主键上的自动递增未被应用,然后我看到一些不一致之处(SQLite抱怨应该是'INTEGER'而不是'int'等)等等。

那么,这是否意味着迁移取决于后端?如果是,它们不应该在嵌套文件夹中创建吗?(例如./Migrations/SQLServer

有人能解释一下这是如何工作的吗?

注意:对于EF Code-First和迁移,我是新手...谢谢!


在切换到使用Entity Frame Core的SQLite之前,请不要忘记阅读限制。https://learn.microsoft.com/en-us/ef/core/providers/sqlite/limitations - habib
3个回答

7
Add-Migration/dotnet ef migrations add命令生成的迁移是特定于后端的,但是您可以手动编辑它们以使其与多个后端兼容。最简单的方法是根据@alwayslearning的回答中描述的生成两组迁移,然后将它们合并为单个迁移集。
例如,一个Id列可能如下所示:
Id = table.Column<int>(nullable: false)
    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
    .Annotation("Sqlite:Autoincrement", true);

您还可以有条件地执行在后端之间可能根本不同的操作:

if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.SqlServer")
{
    // TODO
}
else if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite")
{
    // TODO
}

有没有详细介绍这个的文档? - Greg B
它们需要改进,但是这里它们是:使用多个提供程序进行迁移 - bricelam

3
是的,迁移是依赖于后端的。每个后端都有其特定的规范,因此迁移通常会具有后端特定的列规范。
在某些ORM中,可以以抽象的方式映射“代码优先”模型,并让特定于后端的提供程序将此抽象模型映射到特定于后端的类型,但在任何相对复杂的模型中,保持整个映射与后端无关很难。
要切换到SQLite,您可以更改Startup.cs中注册DbContext的配置,例如:
services.AddDbContext(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")))
然后,您可以使用“dotnet ef migrations add”命令为迁移指定显式路径。 这个问题详细介绍了设置显式文件夹路径的更多细节。

谢谢,我明白了。当我看到我的模型如此干净,没有任何后端依赖时,我感到非常高兴,我认为迁移也将是独立的。实际上,我使用了包管理器控制台中的 Add-MigrationUpdate-Database 命令。希望我能在那里找到一些参数来配置迁移文件夹? - Learner
我已经看到这可能也会有所帮助.. https://learn.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell - Learner

0
public class CompositeMigrationsAnnotationsProvider : IMigrationsAnnotationProvider
{
    private readonly IMigrationsAnnotationProvider[] _providers;

    public CompositeMigrationsAnnotationsProvider(MigrationsAnnotationProviderDependencies dependencies)
    {
        _providers = new IMigrationsAnnotationProvider[] {
            new SqlServerMigrationsAnnotationProvider(dependencies),
            new SqliteMigrationsAnnotationProvider(dependencies) 
        };
    }

    public IEnumerable<IAnnotation> For(IModel model) => _providers.SelectMany(p => p.For(model));
    public IEnumerable<IAnnotation> For(IProperty property) => _providers.SelectMany(p => p.For(property));
    public IEnumerable<IAnnotation> For(IIndex index) => _providers.SelectMany(p => p.For(index));
    public IEnumerable<IAnnotation> For(IKey key) => _providers.SelectMany(p => p.For(key));
    public IEnumerable<IAnnotation> For(IForeignKey foreignKey) => _providers.SelectMany(p => p.For(foreignKey));
    public IEnumerable<IAnnotation> For(IEntityType entityType) => _providers.SelectMany(p => p.For(entityType));
    public IEnumerable<IAnnotation> For(ISequence sequence) => _providers.SelectMany(p => p.For(sequence));
    public IEnumerable<IAnnotation> For(ICheckConstraint checkConstraint) => _providers.SelectMany(p => p.For(checkConstraint)); //EF Core 3.x
    public IEnumerable<IAnnotation> ForRemove(IModel model) => _providers.SelectMany(p => p.ForRemove(model));
    public IEnumerable<IAnnotation> ForRemove(IIndex index) => _providers.SelectMany(p => p.ForRemove(index));
    public IEnumerable<IAnnotation> ForRemove(IProperty property) => _providers.SelectMany(p => p.ForRemove(property));
    public IEnumerable<IAnnotation> ForRemove(IKey key) => _providers.SelectMany(p => p.ForRemove(key));
    public IEnumerable<IAnnotation> ForRemove(IForeignKey foreignKey) => _providers.SelectMany(p => p.ForRemove(foreignKey));
    public IEnumerable<IAnnotation> ForRemove(IEntityType entityType) => _providers.SelectMany(p => p.ForRemove(entityType));
    public IEnumerable<IAnnotation> ForRemove(ISequence sequence) => _providers.SelectMany(p => p.ForRemove(sequence));
    public IEnumerable<IAnnotation> ForRemove(ICheckConstraint checkConstraint) => _providers.SelectMany(p => p.ForRemove(checkConstraint)); //EF Core 3.x
}

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {

    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.ReplaceService<IMigrationsAnnotationProvider, CompositeMigrationsAnnotationsProvider>();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.UseIdentityColumns(); //EF Core 3.x
        modelBuilder.ForSqlServerUseIdentityColumns(); //EF Core 2.x
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接