C# Entity Framework Core Migrations 最佳实践
Posted
技术标签:
【中文标题】C# Entity Framework Core Migrations 最佳实践【英文标题】:C# Entity Framework Core Migrations best praxis 【发布时间】:2022-01-11 11:21:57 【问题描述】:我有一个小程序,它使用EFCore 5.0.12,我还在程序中添加了一个公司和个人模型,它们是我的数据库模型。然后我添加了一个迁移来初始创建表。
然后我为 Person 模型添加了一个 Address 模型,它也应该是一个 DB-Model。进行了第二次迁移,您可以在下面看到。但是,如果我再次运行我的代码,它似乎想要迁移两个迁移。
如何从特定迁移中迁移数据库。
这是我的代码:
这是我的 TestDbContext,它应该完成所有 Db 工作。
public class TestDbContext : DbContext
public DbSet<Company> Companies get; set;
private string _dbPath = Path.Combine(".", "TestDb.sqlite");
public TestDbContext()
if (File.Exists(_dbPath))
Database.Migrate();
else Database.EnsureCreated();
protected override void OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder optionsBuilder)
if (!Directory.Exists(Path.GetDirectoryName(_dbPath)))
Directory.CreateDirectory(Path.GetDirectoryName(_dbPath));
try
optionsBuilder.UseSqlite($"Data Source=Path.GetFullPath(_dbPath)");
catch (Exception ex)
//Log.Error("Could not create DB");
//Log.Error(ex);
return;
我还得到了这个继承自 BaseEntry 的 Company-Model,它拥有一个 ID 字段
public class Company : BaseEntry
public List<Person> Employees get; set; = new List<Person>();
Person-Model 也继承自 BaseEntry 以获取 PrimaryKey。
public class Person : BaseEntry
public string Name get; set;
public string Firstname get; set;
public Address Address get; set;
迁移时应添加的地址。
public class Address : BaseEntry
public string Street get; set;
public uint Number get; set;
public string City get; set;
以及包含 ID 字段的 BaseEntry。
public abstract class BaseEntry
[Key]
public ulong Id get; set;
这是第一次确保表格内容的迁移
protected override void Up(MigrationBuilder migrationBuilder)
migrationBuilder.CreateTable(
name: "Companies",
columns: table => new
Id = table.Column<ulong>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true)
,
constraints: table =>
table.PrimaryKey("PK_Companies", x => x.Id);
);
migrationBuilder.CreateTable(
name: "Person",
columns: table => new
Id = table.Column<ulong>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: true),
Firstname = table.Column<string>(type: "TEXT", nullable: true),
CompanyId = table.Column<ulong>(type: "INTEGER", nullable: true)
,
constraints: table =>
table.PrimaryKey("PK_Person", x => x.Id);
table.ForeignKey(
name: "FK_Person_Companies_CompanyId",
column: x => x.CompanyId,
principalTable: "Companies",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
);
migrationBuilder.CreateIndex(
name: "IX_Person_CompanyId",
table: "Person",
column: "CompanyId");
protected override void Down(MigrationBuilder migrationBuilder)
migrationBuilder.DropTable(
name: "Person");
migrationBuilder.DropTable(
name: "Companies");
然后是第二次迁移,它将地址内容添加到数据库:
protected override void Up(MigrationBuilder migrationBuilder)
migrationBuilder.AddColumn<ulong>(
name: "AddressId",
table: "Person",
type: "INTEGER",
nullable: true);
migrationBuilder.CreateTable(
name: "Address",
columns: table => new
Id = table.Column<ulong>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Street = table.Column<string>(type: "TEXT", nullable: true),
Number = table.Column<uint>(type: "INTEGER", nullable: false),
City = table.Column<string>(type: "TEXT", nullable: true)
,
constraints: table =>
table.PrimaryKey("PK_Address", x => x.Id);
);
migrationBuilder.CreateIndex(
name: "IX_Person_AddressId",
table: "Person",
column: "AddressId");
migrationBuilder.AddForeignKey(
name: "FK_Person_Address_AddressId",
table: "Person",
column: "AddressId",
principalTable: "Address",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
protected override void Down(MigrationBuilder migrationBuilder)
migrationBuilder.DropForeignKey(
name: "FK_Person_Address_AddressId",
table: "Person");
migrationBuilder.DropTable(
name: "Address");
migrationBuilder.DropIndex(
name: "IX_Person_AddressId",
table: "Person");
migrationBuilder.DropColumn(
name: "AddressId",
table: "Person");
但是这个迁移永远不会到达,因为第一次迁移失败是因为 Table 已经存在。我的主要问题是,如何说 EFCore 数据库已经迁移到特定点并且它应该只从该点迁移?
【问题讨论】:
你先搭建脚手架了吗? docs.microsoft.com/en-us/ef/core/managing-schemas/… 【参考方案1】:如果您想告诉 EF 您的第一次迁移已经迁移。您可以手动将其添加到迁移历史表默认表是__EFMigrationsHistory
MigrationId | ProductVersion |
---|---|
2021061200000_initialize_blah_blah | 5.0.1.2 |
your_migration_id | version |
再次进行迁移,它将跳过历史记录表中已经存在的迁移
如果您只是想迁移特定的迁移,您可以告诉它同时 你运行迁移命令
update-database -migration "your-migration"
【讨论】:
谢谢@朝仓游侠。如何以编程方式将此条目添加到此表中? 如果您的目的是迁移特定的迁移,那么您可以从 dbContextyourDbContext.GetService<IMigrator>().Migrate("your_migration");
如果您想添加记录但不能直接访问数据库,您可以从控制台命令和代码运行原始 Sql 脚本。这个:***.com/questions/35184476/… 和这个:***.com/questions/14283082/…以上是关于C# Entity Framework Core Migrations 最佳实践的主要内容,如果未能解决你的问题,请参考以下文章
C# Entity Framework Core Migrations 最佳实践
如何将 C# 8.0 可空引用类型与 Entity Framework Core 模型一起使用?
System.Core 错误:使用 C# Entity Framework 和 Linq 和 Expression 的“代码应该无法访问”
在 C# 中使用 Entity Framework Core 插入数据之前检查重复字符串数据的最佳实践