zoukankan      html  css  js  c++  java
  • T4学习- 4、Kalman Studio-T4代码生成器

    一、简介

    开源代码生成器-Kalman Studio

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

    image

    1、软件主要功能如下:

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

    二、编写T4模板:

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

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

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

    o_TextTemplatingFileGenerator[1]

    2、编写T4模板

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

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

    <#@ template language="C#v3.5" hostSpecific="true" debug="true" #>
    <#@ output extension=".cs" #>
    <# 
        TableHost host = (TableHost)(Host); 
        SOTable table = host.Table;
        List<SOColumn> list = host.ColumnList;
        string columnPrefix = host.GetString("ColumnPrefix");
        int prefixLevel = host.GetInt32("PrefixLevel");
        string nameSpace = host.GetString("NameSpace");
        string className = host.GetString("ClassName");
        if(string.IsNullOrEmpty(nameSpace))nameSpace = "Entity";
        if(string.IsNullOrEmpty(className))className = table.Name;
    #>
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    
    namespace <#= nameSpace #>
    {
        /// <summary>
        /// <#= table.Comment == "" ? table.Name : table.Comment #>
        /// </summary>
        [Serializable]
        public partial class <#= className #>
        {
            <# foreach (SOColumn c in list)
            { #>/// <summary>
            /// <#= c.Comment == "" ? c.Name : c.Comment #>
            /// </summary>
            public <#= TypeUtil.DbType2TypeString(c.DataType) #> <#= StringUtil.RemovePrefix(c.Name, columnPrefix, prefixLevel).Replace(" ", "") #> { get; set; }
            
            <# } #>
            
        }
    }

    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

    image

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

     public override List<SOColumn> GetTableColumnList(SOTable table)
            {
                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 ,
                                                            cast(colm.max_length as int) length, cast(colm.precision as int) precision, cast(colm.scale as int) scale, colm.is_computed
                                                from     sys.columns colm
                                                    inner join sys.types systype on colm.system_type_id = systype.system_type_id and colm.user_type_id = systype.user_type_id
                                                where    colm.object_id = object_id('{0}')
                                                order by colm.column_id;", table.Name, table.Owner, table.Database.Name);
    
                List<SOColumn> columnList = new List<SOColumn>();
                List<string> pkList = GetPrimaryKeys(table);
                DataTable dt = this.DbProvider.ExecuteDataSet(System.Data.CommandType.Text, cmdText).Tables[0];
    
                foreach (DataRow row in dt.Rows)
                {
                    SOColumn column = new SOColumn
                    {
                        Parent = table,
                        Name = row["column_name"].ToString(),
                        DefaultValue = row["column_def"].ToString(),
                        Nullable = row["is_nullable"].ToString()== "True",
                        NativeType = row["type_name"].ToString(),
                        Identify = row["is_identity"].ToString() == "True",
                        Computed = row["is_computed"].ToString() == "True",
                        //ForeignKey
                        Length = ConvertUtil.ToInt32(row["length"], -1),
                        Precision = ConvertUtil.ToInt32(row["precision"], -1),
                        Scale = ConvertUtil.ToInt32(row["scale"], –1),
                    };
    
                    column.PrimaryKey = pkList.Contains(column.Name);
                    column.DataType = this.GetDbType(column.NativeType);
                    column.Comment = GetColumnComment(column);
                    columnList.Add(column);
                }
    
                return columnList;
            }
    View Code

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

    1、生成实体:model.tt

    <#@ template language="C#v3.5" hostSpecific="true" debug="true" #>
    <#@ output extension=".cs" #>
    <# 
        TableHost host = (TableHost)(Host); 
        SOTable table = host.Table;
        List<SOColumn> list = host.ColumnList;
        string nameSpace = host.GetString("NameSpace");
        string className = host.GetString("ClassName");
        if(string.IsNullOrEmpty(nameSpace))nameSpace = "Entity";
        if(string.IsNullOrEmpty(className))className = table.Name;
    #>
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
     
    namespace <#= nameSpace #>
    {
        /// <summary>
        /// <#= table.Comment == "" ? table.Name : table.Comment.Replace("
    "," ") #>
        /// </summary>
        [Serializable]
        public partial class <#= className+"Entity" #>
        {
    <# foreach (SOColumn c in list)
    {#>
            /// <summary>
            /// <#= c.Comment == "" ? c.Name : c.Comment.Replace("
    "," ") #>
            /// </summary>
            public <#= TypeUtil.DbType2TypeString(c.DataType) #><# if(c.Nullable) {  #><#if(TypeUtil.DbType2Type(c.DataType).IsValueType){ #>?<#
     }#><# }#> <#= c.Name #>{get;set;}; 
                
    <# } #>
        }
    }

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

    <#@ template language="C#v3.5" hostSpecific="true" debug="true" #><#@ output extension=".cs" #>
    <# 
        TableHost host = (TableHost)(Host); 
        SOTable table = host.Table;
        List<SOColumn> list = host.ColumnList;
    
        string nameSpace = host.GetString("NameSpace");
        string className = host.GetString("ClassName");
        if(string.IsNullOrEmpty(nameSpace))nameSpace = "DAL";
        if(string.IsNullOrEmpty(className))className = table.Name;
        List<SOColumn> listPK = new List<SOColumn>();
        List<SOColumn> listOtherCol =new List<SOColumn>();
    
        List<string> listAdd =new List<string>();
        List<string> listUpdate =new List<string>();
        foreach (SOColumn c in list)
        {           
          if(c.PrimaryKey)
          {
              listPK.Add(c);
          }
          if((c.PrimaryKey&&!c.Identify) ||!c.PrimaryKey )
            {                
             if( !c.Computed)
             {  
                 listOtherCol.Add(c);
                 listAdd.Add("+ "," + SqlNull(entity." + c.Name + ")");
                 if(!c.PrimaryKey) 
                      listUpdate.Add("+ ","+ c.Name + "="+ SqlNull(entity." + c.Name + ")");
            }  
        }}
    
        //colAll     
         System.Text.StringBuilder sbcolAllStr = new StringBuilder();
         List<string> list1= list.ConvertAll(p=>p.Name);
        for (int i = 0; i < list1.Count; i++)
        {
            sbcolAllStr.Append("t."+list[i] + ",");
            if ((i + 1) % 5 == 0 && (i + 1)!=list1.Count ) sbcolAllStr.Append("
                                             ");
        }
        string colAllStr = sbcolAllStr.ToString().TrimEnd(',');
        
        //colOtherStr
        System.Text.StringBuilder sbcolOtherStr = new StringBuilder();
        List<string> list2= listOtherCol.ConvertAll(p=>p.Name);
        for (int i = 0; i < list2.Count; i++)
        {
           if(list2[i].IndexOf("UpdateUser")>-1||list2[i].IndexOf("UpdateTime")>-1)
                continue;
            sbcolOtherStr.Append(list2[i] + ",");
            if ((i + 1) % 5 == 0  && (i + 1)!=list2.Count) sbcolOtherStr.Append("
                                             ");
        }
        string colOtherStr =  sbcolOtherStr.ToString().TrimEnd(',');
         
         
         //AddStr
        System.Text.StringBuilder sblistAddStr = new StringBuilder();
        for (int i = 0; i < listAdd.Count; i++)
        {
               if(listAdd[i].IndexOf("UpdateUser")>-1||listAdd[i].IndexOf("UpdateTime")>-1)
                continue;
            sblistAddStr.Append(listAdd[i] + "");
            if ((i + 1) % 5 == 0  && (i + 1)!=listAdd.Count) sblistAddStr.Append("
                                             ");
        }
        string listAddStr = System.Text.RegularExpressions.Regex.Replace(sblistAddStr.ToString(), @"^+s*"",""s", "");
        
        //UpdateStr
        System.Text.StringBuilder sblistUpdateStr = new StringBuilder();
        for (int i = 0; i < listUpdate.Count; i++)
        {
               if(listUpdate[i].IndexOf("CreateUser")>-1||listUpdate[i].IndexOf("CreateTime")>-1)
                continue;
            sblistUpdateStr.Append(listUpdate[i] + "");
            if ((i + 1) % 5 == 0  && (i + 1)!=listUpdate.Count) sblistUpdateStr.Append("
                                             ");
        }
        string listUpdateStr = System.Text.RegularExpressions.Regex.Replace(sblistUpdateStr.ToString(), @"^+s*"",", "+ "");
    
    #>
    using System;
    using System.Collections.Generic;
    using System.Data;
    using ZS.Mix.Common;
    using <#= className #>.Entity;
    
    namespace <#= nameSpace #>
    {
        internal class <#= className+"DAL" #> : BaseDAL
        {
            /// <summary>
            /// 分页获取所有记录
            /// </summary>
            public List<<#= className #>Entity>  GetAll(<#= TypeUtil.DbType2TypeString(listPK[0].DataType) #> <#= listPK[0].Name #>, int pageindex, int pagesize)
            {
                string sql = string.Format(@"select <#=colAllStr #>                                                                
                                             from   <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
                                             where  t.<#= listPK[0].Name #>  like '%' + '{0}' + '%'
                                             order by  t.<#= listPK[0].Name #> offset ( {1} - 1 ) * {2} rows fetch next {2} rows only;", <#= listPK[0].Name #>, pageindex, pagesize);
                return Service.SqlTable(sql).ToList<<#= className+"Entity" #>>();
             }
             
            /// <summary>
            /// 获取记录总数
            /// </summary>
            public  int GetCount(<#= TypeUtil.DbType2TypeString(listPK[0].DataType) #> <#= listPK[0].Name #>)
            {
                string sql = string.Format(@"select count(1)  
                                             from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
                                             where  <#= listPK[0].Name #> like '%' + '{0}' + '%';", <#= listPK[0].Name #>);
                return Convert.ToInt32(Service.SqlValueList(sql));
            }
             
            /// <summary>
            /// 获取简要记录
            /// </summary>
            public List<<#= className #>Entity> Get<#= className #>List (<#= TypeUtil.DbType2TypeString(listPK[0].DataType) #> <#= listPK[0].Name #> = "%")
            {
                string sql = string.Format(@"select  <#=colAllStr #>  
                                             from  <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
                                             where t.<#= listPK[0].Name #> like '%' + '{0}' + '%' 
                                             order by t.<#= listPK[0].Name #>", <#= listPK[0].Name #>);
                return Service.SqlTable(sql).ToList<<#= className+"Entity" #>>();
            }
    
            /// <summary>
            /// 获取单个实体
            /// </summary>
            public  <#= className #>Entity Get<#= className #> (<#= TypeUtil.DbType2TypeString(listPK[0].DataType) #> <#= listPK[0].Name #>)
            {
                string sql = string.Format(@" select <#=colAllStr #>  
                                              from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
                                              where  t.<#= listPK[0].Name #> like '%' + '{0}' + '%';", <#= listPK[0].Name #>);
    
                return Service.SqlTable(sql).ToList<<#= className+"Entity" #>>()[0];
            }
            
            /// <summary>
            /// 是否存在该记录
            /// </summary>
            public bool Exists(<#= TypeUtil.DbType2TypeString(listPK[0].DataType) #> <#= listPK[0].Name #>)
            {
                string sql = string.Format(@"declare @TempID int;SELECT @TempID = count(1)
                                              from <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> t
                                             where <#= listPK[0].Name #> = '{0}';
                                            if @TempID = 0
                                                select 0;
                                            else
                                                select  1;", <#= listPK[0].Name #>);
    
                int result = Convert.ToInt32(Service.SqlValueList(sql));
                return result == 1 ? true : false;
            }
            /// <summary>
            ///  增加一条数据
            /// </summary>
            public bool Add(<#= className #>Entity entity)
            {
                string sql = @"INSERT INTO <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #>(
                                             <#= colOtherStr #>    
                                            )VALUES("
                                               <#= listAddStr #>  
                                              + " ) ;";
    
                int rowsAffected = Service.SqlExecute(sql);
                return rowsAffected == 1 ? true : false;
            }
    
            /// <summary>
            ///  更新一条数据
            /// </summary>
            public bool Update(<#= className #>Entity entity)
            {
                string sql = @"UPDATE <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #> SET "
                                             <#= listUpdateStr #> 
                              + " WHERE <#=listPK[0].Name #>= '" + <#= "entity."+listPK[0].Name #> +"';";
    
                int rowsAffected = Service.SqlExecute(sql);
                return rowsAffected == 1 ? true : false;
            }
    
            /// <summary>
            /// 删除一条数据
            /// </summary>
            public bool Delete(<#= TypeUtil.DbType2TypeString(listPK[0].DataType) #> <#= listPK[0].Name #>)
            {
                string sql = string.Format(@"DELETE <#= table.Database.Name + "." + table.SchemaName + "." + table.Name #>
                                             WHERE <#= listPK[0].Name #>='{0}';", <#= listPK[0].Name #>);
    
                int rowsAffected = Service.SqlExecute(sql);
                return rowsAffected == 1 ? true : false;
            }
    }
            

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

    static public object SqlNull(dynamic obj)
    {
        if (obj == null)
        {
            return "null";
        }
    
        string typename = obj.GetType().Name.Equals("Nullable`1") ? obj.GetType().GetGenericArguments()[0].ToString() : obj.GetType().ToString();
    
        if (typename.Equals("System.String") || typename.Equals("System.Boolean"))
        {
            return "'" + obj.ToString() + "'";
        }
        else if (typename.Equals("System.DateTime"))
        {
            return "convert(datetime,'" + obj.ToString() + "') ";
        }
        else
        {
            return obj.ToString();
        }
    }
  • 相关阅读:
    activity生命周期
    logcat
    URI
    intent Filter
    隐式intent
    intent
    訪问远程WAMP 下phpmyadmin
    CFileDialog的使用方法简单介绍
    JAVA wait(), notify(),sleep具体解释
    Android开发之去掉标题栏的三种方法,推荐第三种
  • 原文地址:https://www.cnblogs.com/springsnow/p/10365078.html
Copyright © 2011-2022 走看看