EF Core Migration

概念:Migration数据库迁移

面向对象的ORM开发中,数据库不是程序员手动创建的,而是由Migration工具生成的。关系数据库只是盛放模型数据的一个媒介而已,理想状态下,程序员不用关心数据库的操作。
根据对象的定义变化,自动更新数据库中的表以及表结构的操作,叫做Migration)(迁移)。 迁移可以分为多步(项目进化),也可以回滚。

EF Core 开发环境搭建

用什么数据库
1、EF Core 是对于底层ADO.NET Core的封装,因此ADO.NET Core支持的数据库不一定被EF Core 支持。
2、EF Core支持所有主流的数据库,包括MS SQL Server、Oracle、MySQL、PostgreSQL、SQLLite等。可 以自己实现Provider支持其他数据库。国产数据库支持问题。
3、对于SQLserver支持最完美,MySQL、PostgreSQL也不错。这三者是.NET 圈中用的最多的三个。本课程 主要用SQLServer,如果用其他数据库只需要改一行代码+绕一些小坑即可,大部分代码用法不变。EFCore能尽量屏蔽底层数据库差异。

开发环境搭建

1、经典步骤:建实体类;建配置类Config;建DBContext;生成数据库;编写调用EFCore的业务代码。
2、创建实体类:Book.cs

public class Book
{
	public long Id {get;set;}//主键
	public string Title {get;set;}//标题
	public DateTime PubTime {get;set;}//发布时间
	public double Price {get;set;}//价格
}

3、安装 Microsoft.EntityFrameworkCore.SqlServer工具

Install-Package Microsoft.EntityFrameworkCore.SqlServer

4、创建实现了IEntityTypeConfiguration接口的实体配置类,配置实体类和数据库表的对应关系。

class BookConfig : IEntityTypeConfiguration<Book>
{
    public void Configure(EntityTypeBuilder<Book> builder)
    {
        builder.ToTable("T_Books");
    }
}

5、创建继承自DbContext的类

class MyDbContext:DbContext
{
    public DbSet<Book> Books { get; set; }
    public DbSet<Person> Persons { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlServer
            ("Server=DESKTOP-7K7ADF7;Database=EFCoe;Trusted_Connection=True;MultipleActiveResultSets=True"
            );
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
    }
}

Migration:为了使用生成数据库的工具

① Nuget安装:
Microsoft.EntityFrameworkCore.Tools,
安装前执行Add-Migration等命令会报如下错误

PM> Add-Migration
Add-Migration : 无法将“Add-Migration”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名				称的拼写,如果包括路径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 1
+ Add-Migration
+ ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Add-Migration:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

② 安装后再在“程序包管理器控制台”中执行如下命令:
会自动在项目的Migration文件夹中生成操作数据库的C#代码。

Add-Migration InitialCreate
Build started...
Build succeeded.

③ 代码需要执行后才会应用对数据库的操作。
④ “程序包管理器控制台”中执行:Update-database。

Update-database
Build started...
Build succeeded.

⑤ 查看数据库表是否建成功。

操作实体类中的属性

① 项目开发中,根据需要,可能会在已有的实体中修改、新增、删除表、列等。
② 想要限制Title的最大长度为50,Title字段设置为“不可为空”,并且增加一个不可为空且最大长度为20的 AuthorName属性。
③ 首先在Book实体类中增加一个AuthorName属性。

④ 修改BookConfig:

builder.ToTable("T_Books");
builder.Property(e=>e.Title).HasMaxLength(50).IsRequired();
builder.Property(e=>e.AuthorName).HasMaxLength(20).IsRequired();

⑤ 执行Add-Migration AddAuthorName_ModifyTitle

Add-Migration AddAuthorName_ModifyTitle

⑥ 执行Update-database

Update-database

Migration迁移脚本

1、使用迁移脚本,可以对当前连接的数据库执行编号更高的迁移,这个操作叫做【向上迁移(Up())】,也可以执行把数据库回退到旧的版本,这个操作叫【向下迁移(Down())】。

2、除非有特殊需要,否则不要删除 Migration 文件夹下的代码。

3、分析 Migration 下的代码,分析 UpDown等方法,查看 Migration 编号。

4、数据库的_EFMigrationsHistory表:记录当前数据库曾应用过的迁移脚本,按顺序排列,由EFCore生成维护,不要动此表的数据。

public partial class AddPerson : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "T_Persons",
            columns: table => new
            {
                Id = table.Column<long>(type: "bigint", nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                Name = table.Column<string>(type: "nvarchar(max)", nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_T_Persons", x => x.Id);
            });
    }

    /// <inheritdoc />
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "T_Persons");
    }
}
public partial class AddPerson_Height : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<double>(
            name: "Height",
            table: "T_Persons",
            type: "float",
            nullable: false,
            defaultValue: 0.0);
    }

    /// <inheritdoc />
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropColumn(
            name: "Height",
            table: "T_Persons");
    }
}

Migration其他命令

1、Update-Database XXX
把数据库回滚或升级到XXX的状态,不修改迁移脚本。
回滚到初始版本:
执行 update-database AddPerson

update-database AddPerson
Build started...
Build succeeded.
Acquiring an exclusive lock for migration application. See https://aka.ms/efcore-docs-migrations-lock for more information if this takes too long.
Reverting migration '20250316090938_AddPerson_Height'.
Done.

升级到指定版本:
执行 update-database AddPerson_Height

update-database AddPerson_Height
Build started...
Build succeeded.
Acquiring an exclusive lock for migration application. See https://aka.ms/efcore-docs-migrations-lock for more information if this takes too long.
Applying migration '20250316090938_AddPerson_Height'.
Done.

2、Remove-migration
删除最后一次的迁移脚本,执行成功后_EFMigrationsHistory表中的这条迁移脚本记录也同样会被删除。

Remove-migration
Build started...
Build succeeded.
Removing migration '20250316090938_AddPerson_Height'.
Reverting the model snapshot.
Done.

3、Script-Migration
生成迁移SQL代码,如下所示:

IF OBJECT_ID(N'[__EFMigrationsHistory]') IS NULL
BEGIN
    CREATE TABLE [__EFMigrationsHistory] (
        [MigrationId] nvarchar(150) NOT NULL,
        [ProductVersion] nvarchar(32) NOT NULL,
        CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
    );
END;
GO

BEGIN TRANSACTION;
CREATE TABLE [T_Persons] (
    [Id] bigint NOT NULL IDENTITY,
    [Name] nvarchar(max) NOT NULL,
    CONSTRAINT [PK_T_Persons] PRIMARY KEY ([Id])
);

INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20250316090405_AddPerson', N'9.0.3');

COMMIT;
GO

为什么有Update-Database还要生成SQL脚本?
一般开发环境使用 Update-Database 来修改数据库表结构,Script-Migration用于向生产环境投产或者运维时使用(通过Script-Migration 生成的SQL脚本到生产环境更新数据库表结构)。

生成D版本到F版本的SQL脚本:

Script-Migration AddPerson AddPerson_Height
Build started...
Build succeeded.
BEGIN TRANSACTION;
ALTER TABLE [T_Persons] ADD [Height] float NOT NULL DEFAULT 0.0E0;

INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20250316100002_AddPerson_Height', N'9.0.3');

COMMIT;
GO

生成D版本到最新版本的SQL脚本:

Script-Migration AddPerson_Height
Build started...
Build succeeded.
BEGIN TRANSACTION;
ALTER TABLE [T_Persons] ADD [Width] float NOT NULL DEFAULT 0.0E0;

INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20250316100343_AddPerson_Width', N'9.0.3');

COMMIT;
GO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值