处理 SQLite EF Core 限制 - 基础操作
Dealing with SQLite EF Core Limitations - Basis Operations
根据 Documentation,EF Core SQLite 不支持使用迁移进行数据库开发的一些基本操作(例如删除列、设置外键等)。
那么如何执行简单的数据库结构更改,例如在不丢失数据的情况下删除列并保持快照模型与数据库同步(无需脚手架)?
这样做值得吗?还是我应该首先使用数据库并为模型使用脚手架命令更新?
如果我不能在迁移中执行所有必要的操作来更新我的数据库,那么我就不能利用迁移的好处来恢复我的数据库结构。
那么在 EF-Core-Sqlite 中使用迁移的优势在哪里呢?
ORM 应该减轻工作而不是增加工作的难度。
更新
Sqlite Migrations: Table rebuilds 现在可在 EF Core 5 上使用。
原答案
how to perform simple database structure changes like dropping a column without losing data and keeping the snapshot model in sync with the database (without scaffold)?
EF Core Documentation : Migrations limitations workaround
中描述了主要思想
You can bypass some of these limitations by manually writing code in your migrations to rebuild a table. A table rebuild involves renaming the existing table, creating a new table, copying data to the new table, and deleting the old table.
例如,我们创建了一个数据库,其中包含以下 Blog
table
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Foo { get; set; }
}
...那么我们要删除Foo
.
为此,请删除上面显示的 Blog.Foo
class 属性。
然后添加一个migration生成一个Migration
class.
由于 SQLite 不支持 MigrationBuilder.DropColumn
,我们应该按照文档中的描述修改 Up
迁移方法。
protected override void Up(MigrationBuilder migrationBuilder)
{
// Create temporary Blog table with new schema
migrationBuilder.CreateTable(
name: "Blog_temp_new",
columns: table => new
{
BlogId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Blog", x => x.BlogId);
});
// Copy Blog to Blog_temp_new
migrationBuilder.Sql("INSERT INTO Blog_temp_new (BlogId, Name) SELECT BlogId, Name FROM Blog;");
// Delete Blog
migrationBuilder.DropTable("Blog");
// Rename Blog_temp_new to Blog
migrationBuilder.RenameTable("Blog_temp_new", newName: "Blog");
}
调用 Database.Migrate
.
时将保留所有 Blog
数据及其 BlogId
和 Name
我建议你在一个新项目上尝试这个,使用一个简单的单一 class 就像 Blog
示例。如果您的 table 有约束或索引,您还需要做其他事情。但是,如果您在一个简单的沙箱中进行试验,而不是尝试在您的主项目中修复它,您应该能够轻松地学习如何处理这些问题。
Is it worth the effort
根据我的经验,是的!我发现 Model-First 比 Database-First 更容易使用。我更喜欢尽可能在 C# 中完成所有工作,但如果您是 SQL 专家,那么您可能会有与我不同的看法。 :)
根据 Documentation,EF Core SQLite 不支持使用迁移进行数据库开发的一些基本操作(例如删除列、设置外键等)。 那么如何执行简单的数据库结构更改,例如在不丢失数据的情况下删除列并保持快照模型与数据库同步(无需脚手架)?
这样做值得吗?还是我应该首先使用数据库并为模型使用脚手架命令更新? 如果我不能在迁移中执行所有必要的操作来更新我的数据库,那么我就不能利用迁移的好处来恢复我的数据库结构。 那么在 EF-Core-Sqlite 中使用迁移的优势在哪里呢? ORM 应该减轻工作而不是增加工作的难度。
更新
Sqlite Migrations: Table rebuilds 现在可在 EF Core 5 上使用。
原答案
how to perform simple database structure changes like dropping a column without losing data and keeping the snapshot model in sync with the database (without scaffold)?
EF Core Documentation : Migrations limitations workaround
中描述了主要思想You can bypass some of these limitations by manually writing code in your migrations to rebuild a table. A table rebuild involves renaming the existing table, creating a new table, copying data to the new table, and deleting the old table.
例如,我们创建了一个数据库,其中包含以下 Blog
table
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Foo { get; set; }
}
...那么我们要删除Foo
.
为此,请删除上面显示的 Blog.Foo
class 属性。
然后添加一个migration生成一个Migration
class.
由于 SQLite 不支持 MigrationBuilder.DropColumn
,我们应该按照文档中的描述修改 Up
迁移方法。
protected override void Up(MigrationBuilder migrationBuilder)
{
// Create temporary Blog table with new schema
migrationBuilder.CreateTable(
name: "Blog_temp_new",
columns: table => new
{
BlogId = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Blog", x => x.BlogId);
});
// Copy Blog to Blog_temp_new
migrationBuilder.Sql("INSERT INTO Blog_temp_new (BlogId, Name) SELECT BlogId, Name FROM Blog;");
// Delete Blog
migrationBuilder.DropTable("Blog");
// Rename Blog_temp_new to Blog
migrationBuilder.RenameTable("Blog_temp_new", newName: "Blog");
}
调用 Database.Migrate
.
Blog
数据及其 BlogId
和 Name
我建议你在一个新项目上尝试这个,使用一个简单的单一 class 就像 Blog
示例。如果您的 table 有约束或索引,您还需要做其他事情。但是,如果您在一个简单的沙箱中进行试验,而不是尝试在您的主项目中修复它,您应该能够轻松地学习如何处理这些问题。
Is it worth the effort
根据我的经验,是的!我发现 Model-First 比 Database-First 更容易使用。我更喜欢尽可能在 C# 中完成所有工作,但如果您是 SQL 专家,那么您可能会有与我不同的看法。 :)