EF Core多上下文脚手架如何针对不同上下文渲染对应Handlebars模板
实现方案
你可以通过以下两种方式实现动态适配,优先推荐第一种轻量方案:
方案1:直接修改Handlebars模板做条件判断
直接修改你的DbContext.hbs模板,通过内置的{{class}}变量(代表当前正在生成的上下文类名)做分支判断,动态输出对应内容:
{{> dbimports}} using DA.SomeInternalRepo; namespace {{namespace}} { //This file is autogenerated using EF database first. Do not modify it. Customisations can be made using the .hbs template files public partial class {{class}} : {{#if (eq class "DbFirstGraphQLDataContext")}} DbContext {{else}} DbContextCustomBase {{/if}} { {{#if (eq class "DbFirstGraphQLDataContext")}} public {{class}}(DbContextOptions options) : base(options) {{else}} public {{class}}(DbContextOptions options, IServiceCollection serviceCollection) : base(options, serviceCollection) {{/if}} { } // 剩余原有模板逻辑... } }
这种方式不需要修改任何C#代码,原有脚手架命令无需调整,直接指定-c参数选择要生成的上下文即可自动适配。
方案2:自定义模板数据提供器(适合后续扩展多上下文)
如果后续还会新增更多不同配置的上下文,不想把判断逻辑写死在模板里,可以通过注入自定义模板数据的方式实现:
- 首先实现自定义模板数据提供器:
using EntityFrameworkCore.Scaffolding.Handlebars; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.DependencyInjection; public class CustomTemplateDataProvider : ITemplateDataProvider { private readonly ITemplateDataProvider _defaultProvider; public CustomTemplateDataProvider(ITemplateDataProvider defaultProvider) { _defaultProvider = defaultProvider; } public Dictionary<string, object> Process(Dictionary<string, object> templateData, IModel model) { // 调用默认逻辑填充基础数据 templateData = _defaultProvider.Process(templateData, model); // 获取当前上下文类名 var contextName = templateData["class"].ToString(); // 动态注入基类和构造函数配置 if (contextName == nameof(DbFirstGraphQLDataContext)) { templateData["BaseClass"] = "DbContext"; templateData["ConstructorSignature"] = "public DbFirstGraphQLDataContext(DbContextOptions options) : base(options)"; } else { templateData["BaseClass"] = "DbContextCustomBase"; templateData["ConstructorSignature"] = "public DbFirstOtherDataContext(DbContextOptions options, IServiceCollection serviceCollection) : base(options, serviceCollection)"; } return templateData; } }
- 修改
ScaffoldingDesignTimeServices注册自定义提供器:
public class ScaffoldingDesignTimeServices : IDesignTimeServices { public void ConfigureDesignTimeServices(IServiceCollection serviceCollection) { // 先注册默认Handlebars脚手架 serviceCollection.AddHandlebarsScaffolding(opts=> opts.TemplateData); // 替换默认模板数据提供器 serviceCollection.AddSingleton<ITemplateDataProvider, CustomTemplateDataProvider>(); } }
- 简化
DbContext.hbs模板,直接使用注入的变量即可:
{{> dbimports}} using DA.SomeInternalRepo; namespace {{namespace}} { //This file is autogenerated using EF database first. Do not modify it. Customisations can be made using the .hbs template files public partial class {{class}} : {{BaseClass}} { {{ConstructorSignature}} { } // 剩余原有模板逻辑... } }
注意事项
你提供的DbFirstOtherDataContext代码存在笔误:构造函数名错误写成了DbFirstGraphQLDataContext,实际需要和类名保持一致,生成时注意修正。
内容的提问来源于stack exchange,提问作者Matthew Holmes
相关产品推荐
相关产品推荐

