一、简介

开源代码生成器-Kalman Studio

https://github.com/loamen/Kalman.Studio

1、软件主要功能如下:

  1. 1、基于T4的代码生成工具,根据数据库元数据信息生成代码,支持多数据库,支持批量代码生成;
  2. 2、支持根据PowerDesigner物理模型文件来生成代码;
  3. 3、内置了一个简单的文本编辑器,支持代码高亮显示;
  4. 4、数据库元数据信息浏览工具;
  5. 5、数据库文档生成工具,支持输出wordpdf文件格式;
  6. 6IIS日志解析器,小网站可以用用;
  7. 7、其他工具,字符串相关操作等。

二、编写T4模板:

1、VS自动根据模板自动生成代码

首先,打开Visual Studio,新建一个文本文件,将扩展名改为"tt"

这时Visual Studio会为Entity.tt生成一个对应的类文件Entity.cs。这是因为Visual Studio内置了一个代码生成工具“TextTemplatingFileGenerator”,会自动为每个模板文件生成对应的类文件,如果你在Entity.tt中编辑好模板,然后打开Entity.cs,TextTemplatingFileGenerator会自动解析模板,将代码输出到文件Entity.cs。

2、编写T4模板

我们这里不需要使用TextTemplatingFileGenerator生成代码,把属性面板,“自定义工具”里面的文字“TextTemplatingFileGenerator”删掉,对应的类文件会自动删除;然后可以开始编写模板了。

我这里先展示一个编写好的实体模板,然后再详细说明。

  1. <#@ template language="C#v3.5" hostSpecific="true" debug="true" #>
  2. <#@ output extension=".cs" #>
  3. <#
  4. TableHost host = (TableHost)(Host);
  5. SOTable table = host.Table;
  6. List<SOColumn> list = host.ColumnList;
  7. string columnPrefix = host.GetString("ColumnPrefix");
  8. int prefixLevel = host.GetInt32("PrefixLevel");
  9. string nameSpace = host.GetString("NameSpace");
  10. string className = host.GetString("ClassName");
  11. if(string.IsNullOrEmpty(nameSpace))nameSpace = "Entity";
  12. if(string.IsNullOrEmpty(className))className = table.Name;
  13. #>
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Text;
  17. using System.Data;
  18.  
  19. namespace <#= nameSpace #>
  20. {
  21. /// <summary>
  22. /// <#= table.Comment == "" ? table.Name : table.Comment #>
  23. /// </summary>
  24. [Serializable]
  25. public partial class <#= className #>
  26. {
  27. <# foreach (SOColumn c in list)
  28. { #>/// <summary>
  29. /// <#= c.Comment == "" ? c.Name : c.Comment #>
  30. /// </summary>
  31. public <#= TypeUtil.DbType2TypeString(c.DataType) #> <#= StringUtil.RemovePrefix(c.Name, columnPrefix, prefixLevel).Replace(" ", "") #> { get; set; }
  32.  
  33. <# } #>
  34.  
  35. }
  36. }

3、T4模板语法

  • <#@ template language="C#v3.5" hostSpecific="true" debug="true" #>:可以指定模板使用的语言,hostSpecific="true"表示是否使用特定的host(Kalman Studio里面使用的是TableHost对象,必须实现接口ITextTemplatingEngineHost)。
  • <#@ output extension=".cs" #> : 指定生成文件的扩展名。
  • <#@ assembly name="System.Data" #>:添加程序集引用,如果要使用第三方程序集,那么最好在项目中添加引用,或者加入到GAC。
  • <#@ import namespace="System.Data" #>:导入要使用的命名空间,注意:这里的命名空间必须要在前面指定的程序集里面找得到的,比如我指定命名空间"System.Data","System.Data.Common",这些在程序集System.Data中都有的。
  • <#@ include file="test.tt" #> 导入模板,类似Html的include用法
  • <#   #>:定义代码块
  • <#= #>:定义表达式
  • <#+ #>:定义变量

三、Kalman Studio改进

1、自定义架构对象SchemaObject下的类。

2、自定义T4模板的引擎主机类:T4TemplatingEngineHost

3、自定义SqlServerSchema

更改Kalman项目的SqlServerSchema文件,增加Computed是否是计算字段的判断。

  1. public override List<SOColumn> GetTableColumnList(SOTable table)
  2. {
  3. string cmdText = string.Format(@"use [{2}];select colm.name column_name, object_definition(colm.default_object_id) as column_def, systype.name type_name, colm.is_identity, colm.is_nullable ,
  4. cast(colm.max_length as int) length, cast(colm.precision as int) precision, cast(colm.scale as int) scale, colm.is_computed
  5. from sys.columns colm
  6. inner join sys.types systype on colm.system_type_id = systype.system_type_id and colm.user_type_id = systype.user_type_id
  7. where colm.object_id = object_id('{0}')
  8. order by colm.column_id;", table.Name, table.Owner, table.Database.Name);
  9.  
  10. List<SOColumn> columnList = new List<SOColumn>();
  11. List<string> pkList = GetPrimaryKeys(table);
  12. DataTable dt = this.DbProvider.ExecuteDataSet(System.Data.CommandType.Text, cmdText).Tables[];
  13.  
  14. foreach (DataRow row in dt.Rows)
  15. {
  16. SOColumn column = new SOColumn
  17. {
  18. Parent = table,
  19. Name = row["column_name"].ToString(),
  20. DefaultValue = row["column_def"].ToString(),
  21. Nullable = row["is_nullable"].ToString()== "True",
  22. NativeType = row["type_name"].ToString(),
  23. Identify = row["is_identity"].ToString() == "True",
  24. Computed = row["is_computed"].ToString() == "True",
  25. //ForeignKey
  26. Length = ConvertUtil.ToInt32(row["length"], -),
  27. Precision = ConvertUtil.ToInt32(row["precision"], -),
  28. Scale = ConvertUtil.ToInt32(row["scale"], –),
  29. };
  30.  
  31. column.PrimaryKey = pkList.Contains(column.Name);
  32. column.DataType = this.GetDbType(column.NativeType);
  33. column.Comment = GetColumnComment(column);
  34. columnList.Add(column);
  35. }
  36.  
  37. return columnList;
  38. }

4、常用的几个自定义的T4模板

1、生成实体:model.tt

  1. <#@ template language="C#v3.5" hostSpecific="true" debug="true" #>
  2. <#@ output extension=".cs" #>
  3. <#
  4. TableHost host = (TableHost)(Host);
  5. SOTable table = host.Table;
  6. List<SOColumn> list = host.ColumnList;
  7. string nameSpace = host.GetString("NameSpace");
  8. string className = host.GetString("ClassName");
  9. if(string.IsNullOrEmpty(nameSpace))nameSpace = "Entity";
  10. if(string.IsNullOrEmpty(className))className = table.Name;
  11. #>
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Text;
  15. using System.Data;
  16.  
  17. namespace <#= nameSpace #>
  18. {
  19. /// <summary>
  20. /// <#= table.Comment == "" ? table.Name : table.Comment.Replace("\r\n"," ") #>
  21. /// </summary>
  22. [Serializable]
  23. public partial class <#= className+"Entity" #>
  24. {
  25. <# foreach (SOColumn c in list)
  26. {#>
  27. /// <summary>
  28. /// <#= c.Comment == "" ? c.Name : c.Comment.Replace("\r\n"," ") #>
  29. /// </summary>
  30. public <#= TypeUtil.DbType2TypeString(c.DataType) #><# if(c.Nullable) { #><#if(TypeUtil.DbType2Type(c.DataType).IsValueType){ #>?<#
  31. }#><# }#> <#= c.Name #>{get;set;};
  32.  
  33. <# } #>
  34. }
  35. }

2、生成数据访问层:DAL.tt

  1. <#@ template language="C#v3.5" hostSpecific="true" debug="true" #><#@ output extension=".cs" #>
  2. <#
  3. TableHost host = (TableHost)(Host);
  4. SOTable table = host.Table;
  5. List<SOColumn> list = host.ColumnList;
  6.  
  7. string nameSpace = host.GetString("NameSpace");
  8. string className = host.GetString("ClassName");
  9. if(string.IsNullOrEmpty(nameSpace))nameSpace = "DAL";
  10. if(string.IsNullOrEmpty(className))className = table.Name;
  11. List<SOColumn> listPK = new List<SOColumn>();
  12. List<SOColumn> listOtherCol =new List<SOColumn>();
  13.  
  14. List<string> listAdd =new List<string>();
  15. List<string> listUpdate =new List<string>();
  16. foreach (SOColumn c in list)
  17. {
  18. if(c.PrimaryKey)
  19. {
  20. listPK.Add(c);
  21. }
  22. if((c.PrimaryKey&&!c.Identify) ||!c.PrimaryKey )
  23. {
  24. if( !c.Computed)
  25. {
  26. listOtherCol.Add(c);
  27. listAdd.Add("+ \",\" + SqlNull(entity." + c.Name + ")");
  28. if(!c.PrimaryKey)
  29. listUpdate.Add("+ \","+ c.Name + "=\"+ SqlNull(entity." + c.Name + ")");
  30. }
  31. }}
  32.  
  33. //colAll
  34. System.Text.StringBuilder sbcolAllStr = new StringBuilder();
  35. List<string> list1= list.ConvertAll(p=>p.Name);
  36. for (int i = ; i < list1.Count; i++)
  37. {
  38. sbcolAllStr.Append("t."+list[i] + ",");
  39. if ((i + ) % == && (i + )!=list1.Count ) sbcolAllStr.Append("\r\n ");
  40. }
  41. string colAllStr = sbcolAllStr.ToString().TrimEnd(',');
  42.  
  43. //colOtherStr
  44. System.Text.StringBuilder sbcolOtherStr = new StringBuilder();
  45. List<string> list2= listOtherCol.ConvertAll(p=>p.Name);
  46. for (int i = ; i < list2.Count; i++)
  47. {
  48. if(list2[i].IndexOf("UpdateUser")>-||list2[i].IndexOf("UpdateTime")>-)
  49. continue;
  50. sbcolOtherStr.Append(list2[i] + ",");
  51. if ((i + ) % == && (i + )!=list2.Count) sbcolOtherStr.Append("\r\n ");
  52. }
  53. string colOtherStr = sbcolOtherStr.ToString().TrimEnd(',');
  54.  
  55. //AddStr
  56. System.Text.StringBuilder sblistAddStr = new StringBuilder();
  57. for (int i = ; i < listAdd.Count; i++)
  58. {
  59. if(listAdd[i].IndexOf("UpdateUser")>-||listAdd[i].IndexOf("UpdateTime")>-)
  60. continue;
  61. sblistAddStr.Append(listAdd[i] + "");
  62. if ((i + ) % == && (i + )!=listAdd.Count) sblistAddStr.Append("\r\n ");
  63. }
  64. string listAddStr = System.Text.RegularExpressions.Regex.Replace(sblistAddStr.ToString(), @"^\+\s*"",""\s", "");
  65.  
  66. //UpdateStr
  67. System.Text.StringBuilder sblistUpdateStr = new StringBuilder();
  68. for (int i = ; i < listUpdate.Count; i++)
  69. {
  70. if(listUpdate[i].IndexOf("CreateUser")>-||listUpdate[i].IndexOf("CreateTime")>-)
  71. continue;
  72. sblistUpdateStr.Append(listUpdate[i] + "");
  73. if ((i + ) % == && (i + )!=listUpdate.Count) sblistUpdateStr.Append("\r\n ");
  74. }
  75. string listUpdateStr = System.Text.RegularExpressions.Regex.Replace(sblistUpdateStr.ToString(), @"^\+\s*"",", "+ \"");
  76.  
  77. #>
  78. using System;
  79. using System.Collections.Generic;
  80. using System.Data;
  81. using ZS.Mix.Common;
  82. using <#= className #>.Entity;
  83.  
  84. namespace <#= nameSpace #>
  85. {
  86. internal class <#= className+"DAL" #> : BaseDAL
  87. {
  88. /// <summary>
  89. /// 分页获取所有记录
  90. /// </summary>
  91. public List<<#= className #>Entity> GetAll(<#= TypeUtil.DbType2TypeString(listPK[].DataType) #> <#= listPK[].Name #>, int pageindex, int pagesize)
  92. {
  93. string sql = string.Format(@"select <#=colAllStr #>
  94. from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
  95. where t.<#= listPK[].Name #> like '%' + '{0}' + '%'
  96. order by t.<#= listPK[].Name #> offset ( {} - ) * {} rows fetch next {} rows only;", <#= listPK[0].Name #>, pageindex, pagesize);
  97. return Service.SqlTable(sql).ToList<<#= className+"Entity" #>>();
  98. }
  99.  
  100. /// <summary>
  101. /// 获取记录总数
  102. /// </summary>
  103. public int GetCount(<#= TypeUtil.DbType2TypeString(listPK[].DataType) #> <#= listPK[].Name #>)
  104. {
  105. string sql = string.Format(@"select count(1)
  106. from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
  107. where <#= listPK[].Name #> like '%' + '{0}' + '%';", <#= listPK[0].Name #>);
  108. return Convert.ToInt32(Service.SqlValueList(sql));
  109. }
  110.  
  111. /// <summary>
  112. /// 获取简要记录
  113. /// </summary>
  114. public List<<#= className #>Entity> Get<#= className #>List (<#= TypeUtil.DbType2TypeString(listPK[].DataType) #> <#= listPK[].Name #> = "%")
  115. {
  116. string sql = string.Format(@"select <#=colAllStr #>
  117. from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
  118. where t.<#= listPK[].Name #> like '%' + '{0}' + '%'
  119. order by t.<#= listPK[].Name #>", <#= listPK[0].Name #>);
  120. return Service.SqlTable(sql).ToList<<#= className+"Entity" #>>();
  121. }
  122.  
  123. /// <summary>
  124. /// 获取单个实体
  125. /// </summary>
  126. public <#= className #>Entity Get<#= className #> (<#= TypeUtil.DbType2TypeString(listPK[].DataType) #> <#= listPK[].Name #>)
  127. {
  128. string sql = string.Format(@" select <#=colAllStr #>
  129. from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
  130. where t.<#= listPK[].Name #> like '%' + '{0}' + '%';", <#= listPK[0].Name #>);
  131.  
  132. return Service.SqlTable(sql).ToList<<#= className+"Entity" #>>()[];
  133. }
  134.  
  135. /// <summary>
  136. /// 是否存在该记录
  137. /// </summary>
  138. public bool Exists(<#= TypeUtil.DbType2TypeString(listPK[].DataType) #> <#= listPK[].Name #>)
  139. {
  140. string sql = string.Format(@"declare @TempID int;SELECT @TempID = count(1)
  141. from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
  142. where <#= listPK[].Name #> = '{0}';
  143. if @TempID =
  144. select ;
  145. else
  146. select ;", <#= listPK[0].Name #>);
  147.  
  148. int result = Convert.ToInt32(Service.SqlValueList(sql));
  149. return result == ? true : false;
  150. }
  151. /// <summary>
  152. /// 增加一条数据
  153. /// </summary>
  154. public bool Add(<#= className #>Entity entity)
  155. {
  156. string sql = @"INSERT INTO <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #>(
  157. <#= colOtherStr #>
  158. )VALUES("
  159. <#= listAddStr #>
  160. + " ) ;";
  161.  
  162. int rowsAffected = Service.SqlExecute(sql);
  163. return rowsAffected == ? true : false;
  164. }
  165.  
  166. /// <summary>
  167. /// 更新一条数据
  168. /// </summary>
  169. public bool Update(<#= className #>Entity entity)
  170. {
  171. string sql = @"UPDATE <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> SET "
  172. <#= listUpdateStr #>
  173. + " WHERE <#=listPK[0].Name #>= '" + <#= "entity."+listPK[].Name #> +"';";
  174.  
  175. int rowsAffected = Service.SqlExecute(sql);
  176. return rowsAffected == ? true : false;
  177. }
  178.  
  179. /// <summary>
  180. /// 删除一条数据
  181. /// </summary>
  182. public bool Delete(<#= TypeUtil.DbType2TypeString(listPK[].DataType) #> <#= listPK[].Name #>)
  183. {
  184. string sql = string.Format(@"DELETE <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #>
  185. WHERE <#= listPK[].Name #>='{0}';", <#= listPK[0].Name #>);
  186.  
  187. int rowsAffected = Service.SqlExecute(sql);
  188. return rowsAffected == ? true : false;
  189. }
  190. }

3、注意这个处理null值的函数:

  1. static public object SqlNull(dynamic obj)
  2. {
  3. if (obj == null)
  4. {
  5. return "null";
  6. }
  7.  
  8. string typename = obj.GetType().Name.Equals("Nullable`1") ? obj.GetType().GetGenericArguments()[].ToString() : obj.GetType().ToString();
  9.  
  10. if (typename.Equals("System.String") || typename.Equals("System.Boolean"))
  11. {
  12. return "'" + obj.ToString() + "'";
  13. }
  14. else if (typename.Equals("System.DateTime"))
  15. {
  16. return "convert(datetime,'" + obj.ToString() + "') ";
  17. }
  18. else
  19. {
  20. return obj.ToString();
  21. }
  22. }

T4学习- 4、Kalman Studio-T4代码生成器的更多相关文章

  1. [转]发布基于T4模板引擎的代码生成器[Kalman Studio]

    本文转自:http://www.cnblogs.com/lingyun_k/archive/2010/05/08/1730771.html 自己空闲时间写的一个代码生成器,基于T4模板引擎的,也不仅是 ...

  2. T4学习- 2、创建设计时模板

    使用设计时 T4 文本模板,您可以在 Visual Studio 项目中生成程序代码和其他文件. 通常,您编写一些模板,以便它们根据来自模型的数据来改变所生成的代码. 模型是包含有关应用程序要求的关键 ...

  3. T4学习- 1、简介

    一.T4简介       T4(Text Template Transformation Toolkit)在 Visual Studio 中,"T4 文本模板"是由一些文本块和控制 ...

  4. T4学习- 3、创建运行时模板

    使用 Visual Studio 预处理过的文本模板,可以在运行时在应用程序中生成文本字符串. 执行应用程序的计算机不必具有 Visual Studio. 预处理过的模板有时称为"运行时文本 ...

  5. T4学习资料

    网址:http://www.olegsych.com/2007/12/text-template-transformation-toolkit/

  6. openGL学习:Visual Studio配置OpenGL

    Visual Studio配置OpenGL 分两步: (一)下载glut,并将其放置到适当的位置 (二) 进行vs2005项目属性配置 ******************************** ...

  7. Android学习之Android studio TraceView和lint工具的使用具体解释

    上次讲述了一下Android studio Terminal的使用配置,今天又学习了一下关于Traceview和lint工具的使用. 首先来讲lint吧: Android lint工具是Android ...

  8. 学习OpenCV——Kalman滤波

    背景: 卡尔曼滤波是一种高效率的递归滤波器(自回归滤波器), 它能够从一系列的不完全及包含噪声的测量中,估计动态系统的状态.卡尔曼滤波的一个典型实例是从一组有限的,包含噪声的,对物体位置的观察序列(可 ...

  9. [C++学习历程]Visual Studio 2010 的HelloWorld

    大学时期曾学过C++的知识,那时候也没有使用VS这样高档的IDE工具,就是C++6.0那样来的.对于重新拾起C++来说,换了个IDE,那么就先从使用IDE学起吧~ 作者:苏生米沿 本文链接:http: ...

随机推荐

  1. React Router基础教程

    React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...

  2. [转]论magento1和magento2的速度性能优化问题

    本文转自:http://www.360magento.com/blog/magento-speed-up/ magento从2007年发展至今,也经历了十余年的磨练,如今也迎来了magento的换代产 ...

  3. 乱糟unity整理

    当Canvas上的UI元素变化时,会重新生成网格并向GPU发起绘图调用,从而显示UI.划分画布:1.每块画布上的元素都与其他画布的元素相隔离,使用?工具来切分画布?,从而解决ui的批处理问题.2.也可 ...

  4. EasyUI 添加一行的时候 行号出现负数的解决方案

    原因是:在jquery_easyui.js 看方法 insertRow : function(_736, _737, row) 以下小代码算行号,if (opts.pagination) { _73c ...

  5. HDU4280(KB11-G 最大流)

    Island Transport Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  6. python学习之老男孩python全栈第九期_day015作业_老男孩Python全9期练习题(面试真题模拟)

    一. 选择题(32分) 1. python不支持的数据类型有:AA. charB. intC. floatD. list 2. Ex = ‘foo’y = 2print(x + y)A. fooB. ...

  7. 微信小程序传参数的几种方法

    1,navigator 跳转时 wxml页面(参数多时可用“&”) <navigator url='../index/index?id=1&name=aaa'></n ...

  8. Vue.js之组件系统

    vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. Vue.js组件系统 每一个新技 ...

  9. windows安装mysql数据库

    一.下载安装包.进入mysql官网https://www.mysql.com/ 二.打开安装包安装 以上步骤直接点击next即可,遇到配置密码就配置下

  10. SSM框架下的redis缓存

    基本SSM框架搭建:http://www.cnblogs.com/fuchuanzhipan1209/p/6274358.html 配置文件部分: 第一步:加入jar包 pom.xml <!-- ...