Ef Core花里胡哨系列(7) 使用Ef Core也能维护表架构?

我们这里指的并不是查询,而是利用Ef的迁移原理,生成可用的其它表架构操作的
Sql

例如你想在
Ef Core
里建表,并且可能程序里有多个
provider
,那么写Sql将是一件痛苦的事情,我们就是利用
Ef Core
迁移时的操作,来为我们所用。

如果看过此系列中屏蔽外键的那一篇博客,我们的主角就暗藏在里面,它就是各种
Operation

Operation

Ef Core
中所有的迁移的工作单元均由
Operation
组成,例如
CreateTableOperation

AlterColumnOperation
等等,我们要做的就是将我们的操作组装为对应的
Operation
来模拟迁移的操作,让
Ef Core
去生成
Sql
,那我们在一定程度上就避免了
Sql
的强耦合,生成
Sql
将有
Ef Core
的提供程序来提供支持。

当然我们之前提到过,不同的提供程序可能有些实现是没有的,例如微软官方就不提供
AlterColumnOperation
,直接采用的暴力的
Drop

Add
,我们只需重写
IMigrationsSqlGenerator
中对应的实现即可。

使用
Operation
有两种方法实现:

  • 直接拼接Operation
  • 类似于迁移文件的写法

直接拼接Operation

直接拼接
Operation
需要我们创建对应的
Operation
并且填充里面的主要信息,生成
Sql
时,需要拿到
DbContext
内部的
IMigrationsSqlGenerator
作为服务,用于生成
Sql

var service = CreateDbContext<DataDbContext>().GetService<IMigrationsSqlGenerator>();

var creator = new CreateTableOperation()
{
    Name = "test",
};
creator.Columns.Add(new AddColumnOperation()
{
    Name = "Id",
    ClrType = typeof(int),
    IsNullable = false
});

var operations = new List<MigrationOperation> {
    creator
};

var cmd = service.Generate(operations);

foreach (var item in cmd.Select(x => x.CommandText))
{
    TestOutputHelper.WriteLine(item);
}

类似于迁移文件的写法

类似于迁移文件的写法实现时,和迁移文件中展现的部分基本一样,生成
Sql
时,需要构建一个
MigrationBuilder
并且提供你要使用的
Ef Core
提供程序,
项目里需要引用该提供程序
。随后即可生成对应的
Sql

MigrationBuilder t = new MigrationBuilder("Microsoft.EntityFrameworkCore.SqlServer");

t.CreateTable(
        name: "flow_draft",
        columns: table => new
        {
            ID = table.Column<string>(type: "varchar(36)", maxLength: 36, nullable: false),
            FlowId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false, comment: "流程Id"),
            UserId = table.Column<string>(type: "varchar(255)", nullable: false, comment: "草稿提交人"),
            FormDataId = table.Column<string>(type: "varchar(36)", maxLength: 36, nullable: false, comment: "数据Id"),
            Content = table.Column<string>(type: "longtext", nullable: false, comment: "表单冗余数据")
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_flow_draft", x => x.ID);
        },
        comment: "流程草稿记录")
    .Annotation("MySQL:Charset", "utf8mb4");

cmd = service.Generate(t.Operations);

foreach (var item in cmd.Select(x => x.CommandText))
{
    TestOutputHelper.WriteLine(item);
}

标签: none

添加新评论