Ef Core花里胡哨系列(2) 移除外键、扩展操作

13 篇文章 0 订阅
11 篇文章 0 订阅
本文介绍了如何在保持Codo-First模式的同时,避免EfCore自动生成外键,以及如何重写MigrationsSqlGenerator进行自定义操作,包括修改表、备份表等,以适应特定需求和提高数据处理灵活性。
摘要由CSDN通过智能技术生成

Ef Core花里胡哨系列(2) 移除外键、扩展操作

虽然数据库的外键有着举足轻重的作用,但是在通常的软件设计中,很多人嫌弃麻烦,从而放弃了Ef CoreCodo-First模式而转向Db-First模式。但是Db-First不是很严谨,所以我这里就是提供一种相对折中的方式:在Code-Frist的模式下忽略外键的生成。

总之,外键在数据库中起着重要的作用,可以确保数据的完整性和一致性,简化数据查询和操作,并帮助建立数据库的关系模型。其实还是很有必要的。

重写Ef Core的迁移应用程序

我们无法对Ef Core生成迁移的部分进行操作,或者说操作非常困难,但是我们可以通过重写Ef Core中的MigrationsSqlGenerator来实现迁移文件在向Sql转义时的操作。

public class CustomMigrationsSqlGenerator : MigrationsSqlGenerator
{
    public static ISqlManager SqlManager =>
        SqlManagerHelper.GetSqlManager(AppSettings.Get<DbOptions>()?.GetUseableWriteHost()?.DbType);

    public CustomMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IMigrationsAnnotationProvider migrationsAnnotations) : base(dependencies)
    {
    }

    protected override void Generate(Microsoft.EntityFrameworkCore.Migrations.Operations.CreateTableOperation operation, IModel? model, MigrationCommandListBuilder builder, bool terminate = true)
    {
        operation.ForeignKeys.Clear();
        base.Generate(operation, model, builder, terminate);
    }

    protected override void Generate(AddForeignKeyOperation operation, IModel? model, MigrationCommandListBuilder builder,
        bool terminate = true)
    {
        return;
    }
}

替换Ef Core中的默认实现

services.AddDbContext<SampleDbContext>(opts =>
{
    opts.ReplaceService<IMigrationsSqlGenerator, CustomMigrationsSqlGenerator>();
});

扩展操作

SqlManager是我自己封装的一个Sql生成相关的类,与逻辑无关,可以自己根据需要自行封装。

1 修改表

Ef Core中微软的官方实现为在修改列时,操作为先删除列再添加,我们可以通过重写对应的方法来实现直接修改的操作。

具体就是可以自己根据operation生成Sql使用builder.Append(sql).AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator).EndCommand();来执行。

一些社区的provider是实现了对应的修改方法的,但是微软官方库没有,可以使用这种方法补充。

protected override void Generate(AlterColumnOperation operation, IModel? model, MigrationCommandListBuilder builder)
{
    var sql = SqlManager.Block(SqlManager.GetAlterColumnSql(control, operation.Table,
                oldControl, true)).TrimEnd(';', '\n', '\r');

    builder.Append(sql).AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator).EndCommand();
}

2 备份表

在进行比较具有风险的迁移操作时,可以采用上面类似的方式,将表迁移前的数据和结构导入到一个历史表中。

GetBackupTableSql即根据当前表名将数据导入一个按操作时间命名的表名,例如User20240102

protected override void Generate(DropTableOperation operation, IModel? model, MigrationCommandListBuilder builder, bool terminate = true)
{
    // 删除表和列时会对整个表进行备份,防止使用Migrations的时候误删除
    var sql = SqlManager.Block(SqlManager.GetBackupTableSql(operation.Name)).TrimEnd(';', '\r', '\n');

    builder.Append(sql).AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator).EndCommand();

    base.Generate(operation, model, builder, terminate);
}

protected override void Generate(DropColumnOperation operation, IModel? model, MigrationCommandListBuilder builder, bool terminate = true)
{
    // 删除表和列时会对整个表进行备份,防止使用Migrations的时候误删除
    var sql = SqlManager.Block(SqlManager.GetBackupTableSql(operation.Table)).TrimEnd(';', '\r', '\n');

    builder.Append(sql).AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator).EndCommand();

    base.Generate(operation, model, builder, terminate);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖纸不争

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值