You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让EF Core 2反向工程正确处理复数表名生成单数实体类

解决EF Core 2反向工程复数表名生成单数实体的问题

刚从EF 6.x转EF Core 2的时候我也踩过这个坑,官方默认的反向工程确实会把复数表名直接映射成同名实体,不过不用每次手动修改,给你两个可行的方案:

方案一:用第三方脚手架扩展包(推荐)

EF Core 2.x的官方Scaffold-DbContext命令本身没有直接的复数转单数开关,但可以借助社区的EntityFrameworkCore.Scaffolding.Handlebars包来实现自定义命名规则,步骤如下:

  1. 先在包管理器控制台安装两个必要的包:

    Install-Package EntityFrameworkCore.Scaffolding.Handlebars
    Install-Package Humanizer.Core
    

    (Humanizer是用来处理各种不规则单复数转换的,比如Children转Child,比自己写的简单替换靠谱多了)

  2. 在项目里添加一个设计时服务类,用来配置实体命名规则:

    using Microsoft.EntityFrameworkCore.Design;
    using Microsoft.EntityFrameworkCore.Scaffolding;
    using EntityFrameworkCore.Scaffolding.Handlebars;
    using Humanizer;
    
    public class CustomScaffoldingDesignTimeServices : IDesignTimeServices
    {
        public void ConfigureDesignTimeServices(IServiceCollection services)
        {
            // 注册Handlebars脚手架服务
            services.AddHandlebarsScaffolding();
            // 配置实体和DbSet的命名转换
            services.AddHandlebarsTransformers(transformers =>
            {
                // 把表名单数化作为实体类名
                transformers.EntityNameTransformer = tableName => tableName.Singularize();
                // DbSet的名称保持原表的复数名
                transformers.DbSetNameTransformer = tableName => tableName;
            });
        }
    }
    
  3. 正常运行你的Scaffold-DbContext命令就行,比如:

    Scaffold-DbContext "Server=.;Database=YourDb;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
    

    这时候生成的代码就会是你想要的public virtual DbSet<User> Users { get; set; }了。

方案二:手动批量处理(应急用)

如果不想引入第三方包,也可以在反向工程完成后,用IDE的批量替换功能(比如VS的查找替换,开启正则表达式):

  • 对于实体类名:查找public partial class (\w+)s,替换为public partial class $1(针对规则复数)
  • 对于DbSet的泛型参数:查找DbSet<(\w+)s>,替换为DbSet<$1>

不过这种方法没法处理不规则单复数,还是方案一更稳妥。

内容的提问来源于stack exchange,提问作者Intensivist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:11:38