T4生成整理

2019-09-11 15:18:39 浏览数 (1)

将一些公用的东西弄到一个类库DM.T4里面,哪个项目需要用到t4生成的话,将DM.T4的生成事件中将dll和ModelAuto.ttinclude复制到需要使用T4的项目的生成目录下,如果这样

代码语言:javascript复制
copy $(TargetPath) $(SolutionDir)DM.Domain$(OutDir)
copy $(TargetDir)ModelAuto.ttinclude $(SolutionDir)DM.Domain$(OutDir)

然后在需要就可以添加T4文件了,T4文件头部引入即可,例如下面的这个例子,就是根据表生成一些类

代码语言:javascript复制
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="$(TargetDir)DM.T4.dll"#>
<#@ import namespace="System" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Collections.Generic"#>
<#@ import namespace="System.Text.RegularExpressions"#>
<#@ import namespace="DM.T4"#>
<#@ include file="$(TargetDir)ModelAuto.ttinclude"#>
<#    var manager2 = new Manager(Host, GenerationEnvironment, true) { OutputPath = Path.GetDirectoryName(Host.TemplateFile)}; #>
<# 
    ModelManager manager = new ModelManager();
    List<string> list=manager.GetTableList();
    foreach (var item in list)
    {
        string tableName=item;
        DataTable table= manager.GetTableSchema(tableName);
        string strTableMemo=string.Empty;
        if(table!=null&&table.Rows.Count>0)
        {
            strTableMemo=table.Rows[0]["表说明"].ToString();
        }
        manager2.StartBlock(tableName "Repository.cs");
 #>
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码从T4模板生成。
//     黄正辉(623128629@qq.com)
//     手动更改此文件可能导致应用程序出现意外的行为。
//     如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
using System.Data.Common;
using DM.Domain;
using DM.Tools;
using DM.Interface;
using DM.Interface.IRepository;

namespace DM.Repository.BusinessRepository
{
    /// <summary>
    /// 仓储实现:<#= strTableMemo #> (<#= tableName #>)
    /// </summary>
    public partial class <#=tableName #>Repository :RepositoryBase<<#=tableName #>>,  I<#=tableName #>Repository,IDependency
    {
        /// <summary>
        /// 插入一个数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Insert(<#=tableName #> entity)
        {
            return base.Insert(entity);
        }
        /// <summary>
        /// 插入一个数据列表
        /// </summary>
        /// <param name="entity">实体列表</param>
        /// <returns>受影响行数</returns>
        public virtual int Insert(List<<#=tableName #>> entitys)
        {
            return base.Insert(entitys);
        }
        /// <summary>
        /// 修改一个数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Update(<#=tableName #> entity)
        {
            return base.Update(entity);
        }
        /// <summary>
        /// 删除一个数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Delete(<#=tableName #> entity)
        {
            return base.Delete(entity);
        }
        /// <summary>
        /// 根据表达式删除
        /// </summary>
        /// <param name="predicate">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Delete(Expression<Func<<#=tableName #>, bool>> predicate)
        {
            return base.Delete(predicate);
        }
        /// <summary>
        /// 根据主键查询一个数据
        /// </summary>
        /// <param name="keyValue">主键值</param>
        /// <returns>实体</returns>
        public virtual <#=tableName #> FindEntity(object keyValue)
        {
            return base.FindEntity(keyValue);
        }
        /// <summary>
        /// 根据表达式查询一个数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns>实体</returns>
        public virtual <#=tableName #> FindEntity(Expression<Func<<#=tableName #>, bool>> predicate)
        {
            return base.FindEntity(predicate);
        }
        /// <summary>
        /// 查询IQueryable列表
        /// </summary>
        /// <returns>IQueryable列表</returns>
        public virtual IQueryable<<#=tableName #>> IQueryable()
        {
            return base.IQueryable();
        }
        /// <summary>
        /// 根据表达式查询IQueryable列表数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns>IQueryable列表</returns>
        public virtual IQueryable<<#=tableName #>> IQueryable(Expression<Func<<#=tableName #>, bool>> predicate)
        {
            return base.IQueryable(predicate);
        }
        /// <summary>
        /// 根据Sql查询数据
        /// </summary>
        /// <param name="strSql">Sql</param>
        /// <returns>数据列表</returns>
        public virtual List<<#=tableName #>> FindList(string strSql)
        {
            return base.FindList(strSql);
        }
        /// <summary>
        /// 根据Sql查询数据
        /// </summary>
        /// <param name="strSql">Sql</param>
        /// <param name="dbParameter">参数列表</param>
        /// <returns>数据列表</returns>
        public virtual List<<#=tableName #>> FindList(string strSql, DbParameter[] dbParameter)
        {
            return base.FindList(strSql,dbParameter);
        }
        /// <summary>
        /// 查询分页数据
        /// </summary>
        /// <param name="pagination">分页参数</param>
        /// <returns>数据列表</returns>
        public virtual List<<#=tableName #>> FindList(Pagination pagination)
        {
            return base.FindList(pagination);
        }
        /// <summary>
        /// 查询表达式查询分页数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <param name="pagination">分页参数</param>
        /// <returns>数据列表</returns>
        public virtual List<<#=tableName #>> FindList(Expression<Func<<#=tableName #>, bool>> predicate, Pagination pagination)
        {
            return base.FindList(predicate,pagination);
        }
    }
}
<#        
 
        manager2.EndBlock(); 
    }
    manager2.Process(true);
#>

生成后的结果是这样的

文件的内容如下

代码语言:javascript复制
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码从T4模板生成。
//     黄正辉(623128629@qq.com)
//     手动更改此文件可能导致应用程序出现意外的行为。
//     如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
using System.Data.Common;
using DM.Domain;
using DM.Tools;
using DM.Interface;
using DM.Interface.IRepository;

namespace DM.Repository.BusinessRepository
{
    /// <summary>
    /// 仓储实现: (Sys_Role)
    /// </summary>
    public partial class Sys_RoleRepository :RepositoryBase<Sys_Role>,  ISys_RoleRepository,IDependency
    {
        /// <summary>
        /// 插入一个数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Insert(Sys_Role entity)
        {
            return base.Insert(entity);
        }
        /// <summary>
        /// 插入一个数据列表
        /// </summary>
        /// <param name="entity">实体列表</param>
        /// <returns>受影响行数</returns>
        public virtual int Insert(List<Sys_Role> entitys)
        {
            return base.Insert(entitys);
        }
        /// <summary>
        /// 修改一个数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Update(Sys_Role entity)
        {
            return base.Update(entity);
        }
        /// <summary>
        /// 删除一个数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Delete(Sys_Role entity)
        {
            return base.Delete(entity);
        }
        /// <summary>
        /// 根据表达式删除
        /// </summary>
        /// <param name="predicate">实体</param>
        /// <returns>受影响行数</returns>
        public virtual int Delete(Expression<Func<Sys_Role, bool>> predicate)
        {
            return base.Delete(predicate);
        }
        /// <summary>
        /// 根据主键查询一个数据
        /// </summary>
        /// <param name="keyValue">主键值</param>
        /// <returns>实体</returns>
        public virtual Sys_Role FindEntity(object keyValue)
        {
            return base.FindEntity(keyValue);
        }
        /// <summary>
        /// 根据表达式查询一个数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns>实体</returns>
        public virtual Sys_Role FindEntity(Expression<Func<Sys_Role, bool>> predicate)
        {
            return base.FindEntity(predicate);
        }
        /// <summary>
        /// 查询IQueryable列表
        /// </summary>
        /// <returns>IQueryable列表</returns>
        public virtual IQueryable<Sys_Role> IQueryable()
        {
            return base.IQueryable();
        }
        /// <summary>
        /// 根据表达式查询IQueryable列表数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns>IQueryable列表</returns>
        public virtual IQueryable<Sys_Role> IQueryable(Expression<Func<Sys_Role, bool>> predicate)
        {
            return base.IQueryable(predicate);
        }
        /// <summary>
        /// 根据Sql查询数据
        /// </summary>
        /// <param name="strSql">Sql</param>
        /// <returns>数据列表</returns>
        public virtual List<Sys_Role> FindList(string strSql)
        {
            return base.FindList(strSql);
        }
        /// <summary>
        /// 根据Sql查询数据
        /// </summary>
        /// <param name="strSql">Sql</param>
        /// <param name="dbParameter">参数列表</param>
        /// <returns>数据列表</returns>
        public virtual List<Sys_Role> FindList(string strSql, DbParameter[] dbParameter)
        {
            return base.FindList(strSql,dbParameter);
        }
        /// <summary>
        /// 查询分页数据
        /// </summary>
        /// <param name="pagination">分页参数</param>
        /// <returns>数据列表</returns>
        public virtual List<Sys_Role> FindList(Pagination pagination)
        {
            return base.FindList(pagination);
        }
        /// <summary>
        /// 查询表达式查询分页数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <param name="pagination">分页参数</param>
        /// <returns>数据列表</returns>
        public virtual List<Sys_Role> FindList(Expression<Func<Sys_Role, bool>> predicate, Pagination pagination)
        {
            return base.FindList(predicate,pagination);
        }
    }
}

这样就完成了批量生成文件的功能了

项目是DM.T4的项目结构

ModelAuto.ttinclude

代码语言:javascript复制
<#@ 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"#>

<# 

class Manager
{
    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; }

    public Manager(ITextTemplatingEngineHost host, StringBuilder template, bool commonHeader) {
        this.host = host;
        this.template = template;
        OutputPath = String.Empty;
        strategy = ManagementStrategy.Create(host);
    }

    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);
    }

    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;
            }
        }
    }
}#>

ModelManager.cs

代码语言:javascript复制
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DM.T4
{
    public class ModelManager
    {
        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        private const string CONNECTION_STRING = "Server=.;Initial Catalog=DocumentManage;User ID=sa;Password=123456";
        /// <summary>
        /// 用户信息表名
        /// </summary>
        private const string PERSONINFO_TABLE_NAME = "USERINFO";
        /// <summary>
        /// 根据表名查询表结构信息
        /// </summary>
        private const string SELECT_SCHEMA_BY_TABLE_NAME = @"select d.name as 表名       --如果表名相同就返回空  
     , ddd.value as 表说明      --如果表名相同就返回空  
     , a.colorder                                       as 字段序号
     , a.name                                           as 字段名
     , (case
            when columnproperty(a.id, a.name, 'IsIdentity') = 1 then
                1
            else
                0
        end
       )                                                as 是否自增标识
     , (case
            when
            (
                select count(*)
                from sys.sysobjects --查询主键  
                where (name in
                       (
                           select name
                           from sys.sysindexes
                           where (id = a.id)
                                 and (indid in
                                      (
                                          select indid
                                          from sys.sysindexkeys
                                          where (id = a.id)
                                                and (colid in
                                                     (
                                                         select colid from sys.syscolumns where (id = a.id) and (name = a.name)
                                                     )
                                                    )
                                      )
                                     )
                       )
                      )
                      and (xtype = 'PK')
            ) > 0 then
                1
            else
               0
        end
       )                                                as 主键       --查询主键END  
     , b.name                                           as 数据类型
     , a.length                                         as 占用字节数
     , columnproperty(a.id, a.name, 'PRECISION')        as 长度
     , isnull(columnproperty(a.id, a.name, 'Scale'), 0) as 小数位
     , (case
            when a.isnullable = 1 then
                1
            else
                0
        end
       )                                                as 允许空
     , isnull(e.text, '')                               as 缺省值
     , isnull(g.value, '')                              as 备注
from sys.syscolumns                   a
    left join sys.systypes            b
        on a.xtype = b.xusertype
    inner join sys.sysobjects         d
        on a.id = d.id
           and d.xtype = 'U'
           and d.name <> 'dtproperties'
    left outer join
    (
        select major_id
             , value
        from sys.extended_properties
        where name = 'MS_Description'
              and minor_id = 0
    )                                 as ddd
        on a.id = ddd.major_id
    left join sys.syscomments         e
        on a.cdefault = e.id
    left join sys.extended_properties g
        on a.id = g.major_id
           and a.colid = g.minor_id
where d.name='{0}'
order by a.id
       , a.colorder;";

        private const string TABLE_FK_SQL = @"select
a.name as 约束名,
object_name(b.parent_object_id) as 外键表,
c.name as 外键列,
object_name(b.referenced_object_id) as 主健表,
d.name as 主键列
from sys.foreign_keys A
inner join sys.foreign_key_columns B on A.object_id=b.constraint_object_id
inner join sys.columns C on B.parent_object_id=C.object_id and B.parent_column_id=C.column_id 
inner join sys.columns D on B.referenced_object_id=d.object_id and B.referenced_column_id=D.column_id 
where  object_name(b.parent_object_id)!=object_name(b.referenced_object_id)";

        /// <summary>
        /// 获得数据连接
        /// </summary>
        /// <returns></returns>
        private SqlConnection GetConnection()
        {
            return new SqlConnection(SqlHelper.sqlConnectionStr);
        }

        /// <summary>
        /// 得到当前用户的所有表名
        /// </summary>
        /// <returns></returns>
        public List<string> GetTableList()
        {
            string sql = "select table_name from information_schema.tables";
            DataTable dt = SqlHelper.ExecuteDataTable(sql);
            List<string> list = new List<string>();
            if (dt != null && dt.Rows.Count > 0)
            {
                for (int i = 0; i < dt.Rows.Count; i  )
                {
                    list.Add(dt.Rows[i][0].ToString());
                }
            }
            return list;
        }

        /// <summary>
        /// 得到所有表主外键关系
        /// </summary>
        /// <returns></returns>
        public List<FK> GetFK()
        {
            DataTable dt = SqlHelper.ExecuteDataTable(TABLE_FK_SQL);
            List<FK> lst = new List<FK>();
            for (int i = 0; i < dt.Rows.Count; i  )
            {
                FK fk = new FK()
                {
                    FKName = dt.Rows[i]["约束名"].ToString(),
                    WJ_Table = dt.Rows[i]["外键表"].ToString(),
                    WJ_Field = dt.Rows[i]["外键列"].ToString(),
                    ZJ_Table = dt.Rows[i]["主健表"].ToString(),
                    ZJ_Field = dt.Rows[i]["主键列"].ToString()
                };
                lst.Add(fk);
            }

            return lst;
        }
        /// <summary>
        /// 释放连接
        /// </summary>
        /// <param name="con"></param>
        private void ReleaseConnection(SqlConnection con)
        {
            if (con != null)
            {
                if (con.State == ConnectionState.Open)
                {
                    con.Close();
                }
            }
        }

        public DataTable GetTableSchema(string tableName)
        {
            DataTable dt = SqlHelper.ExecuteDataTable(string.Format(SELECT_SCHEMA_BY_TABLE_NAME, tableName));
            return dt;
        }

        /// <summary>
        /// SQL[不完善,需要的自己改造]
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public string TransFromSqlType(string type)
        {
            type = type.ToLower();

            switch (type)
            {
                case "int": return "int";
                case "bigint": return "Int64";
                case "smallint": return "Int16";
                case "text":
                case "char":
                case "nchar":
                case "ntext":
                case "nvarchar":
                case "varchar": return "string";
                case "varbinary":
                case "image":
                case "binary": return "Byte[]";
                case "tinyint": return "byte";
                case "bit": return "bool";
                case "date":
                case "time":
                case "smalldatetime":
                case "timestamp":
                case "datetime": return "DateTime";
                case "money":
                case "numeric":
                case "smallmoney":
                case "decimal": return "decimal";
                case "float": return "double";
                case "real": return "Single";
                default: return "string";
            }
        }
    }
    public class FK
    {
        public string FKName { get; set; }
        public string WJ_Table { get; set; }
        public string WJ_Field { get; set; }
        public string ZJ_Table { get; set; }
        public string ZJ_Field { get; set; }
    }
}

SqlHelper.cs

代码语言:javascript复制
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DM.T4
{
    public class SqlHelper
    {
        public static string sqlConnectionStr = "Server=.;Initial Catalog=DocumentManage;User ID=sa;Password=123456";
        public static DataTable ExecuteDataTable(string sql, params SqlParameter[] paramList)
        {
            using (SqlConnection conn = new SqlConnection(sqlConnectionStr))
            {
                conn.Open();
                using (SqlCommand command = conn.CreateCommand())
                {
                    command.CommandText = sql;
                    command.Parameters.AddRange(paramList);
                    DataTable dt = new DataTable();
                    SqlDataAdapter adapter = new SqlDataAdapter(command);
                    adapter.Fill(dt);
                    return dt;
                }
            }
        }

        public static int ExecuteNonQuery(string sql, params SqlParameter[] paramList)
        {
            using (SqlConnection conn = new SqlConnection(sqlConnectionStr))
            {
                conn.Open();
                using (SqlCommand command = conn.CreateCommand())
                {
                    command.CommandText = sql;
                    command.Parameters.AddRange(paramList);
                    return command.ExecuteNonQuery();
                }
            }
        }

        public static object ExecuteScalar(string sql, params SqlParameter[] paramList)
        {
            using (SqlConnection conn = new SqlConnection(sqlConnectionStr))
            {
                conn.Open();
                using (SqlCommand command = conn.CreateCommand())
                {
                    command.CommandText = sql;
                    command.Parameters.AddRange(paramList);
                    return command.ExecuteScalar();
                }
            }
        }
    }

}

0 人点赞