如何运行EntityFramework.CodeTemplates.CSharp并配置自定义T4模板
我来一步步帮你搞定这个问题,毕竟刚接触T4模板的时候,确实容易卡在这些细节环节上:
一、配置环境,让自定义模板出现在EF模型创建选项里
首先得让Visual Studio识别你的修改后的模板,这样新建EF数据模型时能直接选它:
- 找到模板的安装位置:如果是通过NuGet安装的
EntityFramework.CodeTemplates.CSharp,模板文件会在项目的packages\EntityFramework.CodeTemplates.CSharp.[版本号]\Content目录下;如果是全局安装的,路径一般是%USERPROFILE%\Documents\Visual Studio [你的VS版本]\Templates\ItemTemplates\Visual C#\Data。 - 自定义模板集:建议复制一份原始模板文件夹,改个辨识度高的名字(比如
MyCustomEFCodeTemplates),把你修改后的.tt文件替换进去,再把这个文件夹放到上述的ItemTemplates目录里。 - 重启Visual Studio:之后新建「ADO.NET Entity Data Model」时,在选择生成方式(比如Code First from Database)的步骤里,就能看到你的自定义模板选项了。
二、手动运行模板(测试修改效果用)
如果不想每次都新建模型测试,你可以手动生成DbModel并传给模板:
- 先在项目里准备好基础的EF上下文和实体类,或者通过EF向导生成一个初始模型。
- 写一段小代码生成
DbModel实例:
using System.Data.Entity; using System.Data.Entity.Infrastructure; // 假设你已经有一个DbContext子类 public class MyTestContext : DbContext { public DbSet<Product> Products { get; set; } } class Program { static void Main(string[] args) { using (var context = new MyTestContext()) { // 从现有DbContext生成DbModel var dbModel = ((IObjectContextAdapter)context).ObjectContext.CreateModel(); // 现在这个dbModel就是模板需要的参数了 } } }
- 调试模板时,可以暂时把模板里的参数改成硬编码测试,或者安装Visual Studio的T4 Editor扩展,直接在模板里传入生成的
DbModel进行调试。
三、搞懂System.Data.Entity.Infrastructure.DbModel的生成
DbModel是EF用来描述整个数据模型(实体、关系、映射规则等)的元数据容器,它的生成主要有两种方式:
- 从现有DbContext生成:就是上面代码里的方法,EF会根据你DbContext中的配置(DbSet、数据注解、Fluent API)自动构建模型元数据。
- 用DbModelBuilder手动构建:如果没有现成的DbContext,也可以手动配置模型再生成:
var modelBuilder = new DbModelBuilder(); // 手动配置实体映射 modelBuilder.Entity<Product>().ToTable("Products").HasKey(p => p.Id); // 指定数据库提供程序,生成DbModel var dbModel = modelBuilder.Build(new DbProviderInfo("System.Data.SqlClient", "2008"));
其实Visual Studio的EF模型向导背后就是这么做的:连接数据库读取元数据→构建DbModel→把它作为参数传给T4模板生成代码。
四、运行模板的注意事项
- 确保模板里引用了必要的程序集,比如:
<#@ assembly name="System.Data.Entity" #> <#@ assembly name="System.Core" #>
- 遍历
DbModel时要注意元数据的结构,比如获取实体类型、属性的示例:
<# foreach (var entity in Model.ConceptualModel.EntityTypes) { #> public class <#= entity.Name #> { <# foreach (var property in entity.Properties.Where(p => !p.IsNavigationProperty)) { #> public <#= property.TypeUsage.EdmType.Name #> <#= property.Name #> { get; set; } <# } #> } <# } #>
内容的提问来源于stack exchange,提问作者China Syndrome
相关产品推荐
相关产品推荐

