基于数据库的vs2019的T4模版代码生成器基于sqlserver数据库
Posted 谢文宇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于数据库的vs2019的T4模版代码生成器基于sqlserver数据库相关的知识,希望对你有一定的参考价值。
总体介绍
参考文档:
https://www.cnblogs.com/laozhang-is-phi/p/9757999.html
只想用 ADO.NET 搭建多层框架,动软代码生成器是一个不错的选择。
T4 (Text Template Transformation Toolkit) 是微软官方在 VisualStudio 2008+ 中开始使用的代码生成引擎。在 Visual Studio 中,“T4 文本模板”是由一些文本块和控制逻辑组成的混合模板,它可以生成文本文件。 在 Visual C# 或 Visual Basic 中,控制逻辑编写为程序代码的片段。生成的文件可以是任何类型的文本,例如网页、资源文件或任何语言的程序源代码。现在的VS中只要与代码生成相关的场景基本上都能找T4的身影,比如MVC的视图模板,Entity Framwork的DataContext模板等等。
这里就不具体讲解 T4 语法了,大家可以自行学习,其实很简单,主要还是 C# 代码,下边你看过之后就能懂了,咱们首先先实现之前留下的一个伏笔 —— 将我们的数据库表利用T4 模板生成实体类,也就是 DbFirst。
1、首先在我们的项目中,新建一个类库 Xwy.Core.FrameWorkT4
2、在该类库下,新建文件夹 Xwy.Core.FrameWorkT4.Entity,用于单独存放我们的模板以及生成的实体类文件
3、 ModelAuto.ttinclude 文本文件代码
//引入命名空间 <#@ assembly name="System.Core"#> <#@ assembly name="EnvDTE"#> <#@ import namespace="System.Collections.Generic"#> <#@ import namespace="System.IO"#> <#@ import namespace="System.Text"#> <#@ import namespace="Microsoft.VisualStudio.TextTemplating"#> <#+ //定义管理者 manager 实体类 class Manager { //定义一个 block 块,主要是应用在批量生产中 public struct Block { public String Name; public int Start, Length; } public List<Block> blocks = new List<Block>(); public Block currentBlock; public Block footerBlock = new Block(); public Block headerBlock = new Block(); public ITextTemplatingEngineHost host; public ManagementStrategy strategy; public StringBuilder template; public String OutputPath { get; set; } //构造函数,包含 host主机,模板,输出路径,创建管理策略 public Manager(ITextTemplatingEngineHost host, StringBuilder template, bool commonHeader) { this.host = host; this.template = template; OutputPath = String.Empty; strategy = ManagementStrategy.Create(host); } //开辟一个 block 块 public void StartBlock(String name) { currentBlock = new Block { Name = name, Start = template.Length }; } public void StartFooter() { footerBlock.Start = template.Length; } public void EndFooter() { footerBlock.Length = template.Length - footerBlock.Start; } public void StartHeader() { headerBlock.Start = template.Length; } public void EndHeader() { headerBlock.Length = template.Length - headerBlock.Start; } public void EndBlock() { currentBlock.Length = template.Length - currentBlock.Start; blocks.Add(currentBlock); } //定义进程,用来将所有的 blocks 块执行出来 public void Process(bool split) { String header = template.ToString(headerBlock.Start, headerBlock.Length); String footer = template.ToString(footerBlock.Start, footerBlock.Length); blocks.Reverse(); foreach(Block block in blocks) {//遍历 //输出文件 String fileName = Path.Combine(OutputPath, block.Name); if (split) { String content = header + template.ToString(block.Start, block.Length) + footer; strategy.CreateFile(fileName, content); template.Remove(block.Start, block.Length); } else { strategy.DeleteFile(fileName); } } } } //定义管理策略类 class ManagementStrategy { internal static ManagementStrategy Create(ITextTemplatingEngineHost host) { return (host is IServiceProvider) ? new VSManagementStrategy(host) : new ManagementStrategy(host); } internal ManagementStrategy(ITextTemplatingEngineHost host) { } internal virtual void CreateFile(String fileName, String content) { File.WriteAllText(fileName, content); } internal virtual void DeleteFile(String fileName) { if (File.Exists(fileName)) File.Delete(fileName); } } class VSManagementStrategy : ManagementStrategy { private EnvDTE.ProjectItem templateProjectItem; internal VSManagementStrategy(ITextTemplatingEngineHost host) : base(host) { IServiceProvider hostServiceProvider = (IServiceProvider)host; if (hostServiceProvider == null) throw new ArgumentNullException("Could not obtain hostServiceProvider"); EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE)); if (dte == null) throw new ArgumentNullException("Could not obtain DTE from host"); templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile); } //创建文件 internal override void CreateFile(String fileName, String content) { base.CreateFile(fileName, content); ((EventHandler)delegate { templateProjectItem.ProjectItems.AddFromFile(fileName); }).BeginInvoke(null, null, null, null); } //删除文件 internal override void DeleteFile(String fileName) { ((EventHandler)delegate { FindAndDeleteFile(fileName); }).BeginInvoke(null, null, null, null); } //根据文件名删除文件 private void FindAndDeleteFile(String fileName) { foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems) { if (projectItem.get_FileNames(0) == fileName) { projectItem.Delete(); return; } } } }#>
5 DbHelper.ttinclude文本文件
//引入命名空间 <#@ assembly name="System.Core"#> <#@ assembly name="EnvDTE"#> <#@ import namespace="System.Collections.Generic"#> <#@ import namespace="System.IO"#> <#@ import namespace="System.Text"#> <#@ import namespace="Microsoft.VisualStudio.TextTemplating"#> <#+ //定义管理者 manager 实体类 class Manager { //定义一个 block 块,主要是应用在批量生产中 public struct Block { public String Name; public int Start, Length; } public List<Block> blocks = new List<Block>(); public Block currentBlock; public Block footerBlock = new Block(); public Block headerBlock = new Block(); public ITextTemplatingEngineHost host; public ManagementStrategy strategy; public StringBuilder template; public String OutputPath { get; set; } //构造函数,包含 host主机,模板,输出路径,创建管理策略 public Manager(ITextTemplatingEngineHost host, StringBuilder template, bool commonHeader) { this.host = host; this.template = template; OutputPath = String.Empty; strategy = ManagementStrategy.Create(host); } //开辟一个 block 块 public void StartBlock(String name) { currentBlock = new Block { Name = name, Start = template.Length }; } public void StartFooter() { footerBlock.Start = template.Length; } public void EndFooter() { footerBlock.Length = template.Length - footerBlock.Start; } public void StartHeader() { headerBlock.Start = template.Length; } public void EndHeader() { headerBlock.Length = template.Length - headerBlock.Start; } public void EndBlock() { currentBlock.Length = template.Length - currentBlock.Start; blocks.Add(currentBlock); } //定义进程,用来将所有的 blocks 块执行出来 public void Process(bool split) { String header = template.ToString(headerBlock.Start, headerBlock.Length); String footer = template.ToString(footerBlock.Start, footerBlock.Length); blocks.Reverse(); foreach(Block block in blocks) {//遍历 //输出文件 String fileName = Path.Combine(OutputPath, block.Name); if (split) { String content = header + template.ToString(block.Start, block.Length) + footer; strategy.CreateFile(fileName, content); template.Remove(block.Start, block.Length); } else { strategy.DeleteFile(fileName); } } } } //定义管理策略类 class ManagementStrategy { internal static ManagementStrategy Create(ITextTemplatingEngineHost host) { return (host is IServiceProvider) ? new VSManagementStrategy(host) : new ManagementStrategy(host); } internal ManagementStrategy(ITextTemplatingEngineHost host) { } internal virtual void CreateFile(String fileName, String content) { File.WriteAllText(fileName, content); } internal virtual void DeleteFile(String fileName) { if (File.Exists(fileName)) File.Delete(fileName); } } class VSManagementStrategy : ManagementStrategy { private EnvDTE.ProjectItem templateProjectItem; internal VSManagementStrategy(ITextTemplatingEngineHost host) : base(host) { IServiceProvider hostServiceProvider = (IServiceProvider)host; if (hostServiceProvider == null) throw new ArgumentNullException("Could not obtain hostServiceProvider"); EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE)); if (dte == null) throw new ArgumentNullException("Could not obtain DTE from host"); templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile); } //创建文件 internal override void CreateFile(String fileName, String content) { base.CreateFile(fileName, content); ((EventHandler)delegate { templateProjectItem.ProjectItems.AddFromFile(fileName); }).BeginInvoke(null, null, null, null); } //删除文件 internal override void DeleteFile(String fileName) { ((EventHandler)delegate { FindAndDeleteFile(fileName); }).BeginInvoke(null, null, null, null); } //根据文件名删除文件 private void FindAndDeleteFile(String fileName) { foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems) { if (projectItem.get_FileNames(0) == fileName) { projectItem.Delete(); return; } } } }#>
6 模板文件Entity.tt
//如果要获取主机信息,记得把 hostspecific 设置成true <#@ template debug="false" hostspecific="True" language="C#" #> <#@ output extension=".cs" #> //导入命名空间组件 <#@ assembly name="System.Data" #> <#@ assembly name="System.xml" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.Data.SqlClient" #> <#@ import namespace="System.Data" #> <#@ assembly name="System.Core.dll" #> <#@ assembly name="System.Data.DataSetExtensions.dll" #> <#@ import namespace="System" #> <#@ import namespace="System.Xml" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.IO" #> //引入我们的公共模板文件 <#@ include file="$(ProjectDir)DbHelper.ttinclude" #> <#@ include file="$(ProjectDir)ModelAuto.ttinclude" #> //定义我们的输出文件夹 <# var OutputPath1 = Path.GetDirectoryName(Host.TemplateFile)+"\\\\work"; if (!Directory.Exists(OutputPath1)) { Directory.CreateDirectory(OutputPath1); } var manager = new Manager(Host, GenerationEnvironment, true) { OutputPath = OutputPath1 }; #> //-------------------------------------------------------------------- // 此代码由T4模板自动生成 // 老张的哲学 生成时间 <#=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")#> // 注意更新后会改变相应代码。 //-------------------------------------------------------------------- <# var tableName=config.TableName;//获取config配置中的表名,为单一生产使用 #> <# if(tableName!=""){//如果表名有值,表示是生成单一文件 #> //引用命名空间 using System; namespace Blog.Core.FrameWork.Entity { /// <summary> /// <#=tableName#> /// </summary> public class <#=tableName#>//可以在这里加上基类等 { //将全部字段遍历出来 <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, config.TableName)){#> public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; } <#}#> } } //如果为空,表示要将整个数据库都生成出来 <# } else{ #> //连接数据库,打开 connect 连接 <# SqlConnection conn = new SqlConnection(config.ConnectionString); conn.Open(); System.Data.DataTable schema = conn.GetSchema("TABLES"); #> //遍历全部数据库表 <# foreach(System.Data.DataRow row in schema.Rows) { #> //开始启动block块,参数是实体类文件名 <# manager.StartBlock(row["TABLE_NAME"]+".cs"); #> using System; namespace Blog.Core.FrameWork.Entity { /// <summary> /// <#=tableName#> /// </summary> public class <#=row["TABLE_NAME"].ToString()#>//可以在这里加上基类等 { //将该表下的字段都遍历出来,可以自定义获取数据描述等信息 <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, row["TABLE_NAME"].ToString() )){ #> public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName #> { get; set; } <#}#> } } <# manager.EndBlock(); } manager.Process(true); } #>
以上是关于基于数据库的vs2019的T4模版代码生成器基于sqlserver数据库的主要内容,如果未能解决你的问题,请参考以下文章