在.Net Core中使用T4工具生成实体文件

Posted letnet

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在.Net Core中使用T4工具生成实体文件相关的知识,希望对你有一定的参考价值。

多说无益直接代码伺候。

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"#>

<#+

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

创建一个*.tt模板文件,实例代码数据库使用的Oracle数据库。模板内容和数据库连接需要自行修改。

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Data.OracleClient" #>
<#@ assembly name="System.Xml" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.OracleClient" #>
<#@ import namespace="System.Collections.Generic"#>
<#@ include file="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);
 #>

 <# 
        manager2.StartBlock(tableName+".cs");
 #>
using System;
using Dapper.Contrib.Extensions;namespace ABC.Entitys
{
    /// <summary>
    /// 
    /// </summary>
    [Table("<#= tableName #>")]
    public class <#= tableName #> : Entity
    {
<#
foreach(DataRow row in table.Rows)
{
#>
       /// <summary>
       /// <#=row["备注"]#>
       /// </summary>
<# if(row["主键"].ToString() == "1") { #>       [ExplicitKey]
<#} #>       public <#= manager.TransFromSqlType(row["数据类型"].ToString())#> <#=row["字段名"]#> { get; set; }

<#}
#>
    }
}

<# manager2.EndBlock(); #>

<#
    }  
 #>     
   
<# manager2.Process(true); #>

<#+
    public class ModelManager
    {
        /// <summary>
        /// 根据表名查询表结构信息
        /// </summary>
        private const string SELECT_SCHEMA_BY_TABLE_NAME = @"
        with C as(
          select c1.table_name, c2.column_name, c2.position
            from user_constraints c1, user_cons_columns c2
           where c1.constraint_name = c2.constraint_name
             and c2.position=1
             and c1.constraint_type = ‘P‘
        )
        SELECT A.column_name    字段名,
               A.data_type      数据类型,
               A.data_length    长度,
               A.data_precision 整数位,
               A.Data_Scale     小数位,
               A.nullable       允许空值,
               A.Data_default   缺省值,
               B.comments       备注,
               A.TABLE_NAME     表名,
               (case when C.column_name is null then 0 else 1 end)      主键
          FROM user_tab_columns A
            join user_col_comments B on A.COLUMN_NAME = B.column_name and A.Table_Name = B.Table_Name
            left join C on C.Table_Name = A.Table_Name and C.column_name = A.column_name
        where A.Table_Name = ‘{0}‘";


        /// <summary>
        /// 得到当前用户的所有表名
        /// </summary>
        /// <returns></returns>
        public List<string> GetTableList()
        {
            string sql = "SELECT * FROM USER_TABLES t";
            DataTable dt = OracleHelper.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]["TABLE_NAME"].ToString());
                } 
            }
            return list;
         }

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

        /// <summary>
        /// SQL[不完善,需要的自己改造]
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public string TransFromSqlType(string type)
        {
            if (string.IsNullOrEmpty(type))
            {
                return string.Empty;
            }
            if (string.Equals(type, "number", StringComparison.OrdinalIgnoreCase))
            {
                return "decimal";
            }
            if (string.Equals(type, "date", StringComparison.OrdinalIgnoreCase))
            {
                return "DateTime";
            }
            else if (string.Equals(type, "nvarchar2", StringComparison.OrdinalIgnoreCase))
            {
                return "string";
            }
            return "string";
        }
    }
#>

<#+ 
public class OracleHelper
    {

        private static string oracleConnectionStr = "data source= (DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = eclorcl)));user id=abc;password=123456";
        public static DataTable ExecuteDataTable(string sql, params OracleParameter[] paramList)
        {
            using (OracleConnection conn = new OracleConnection(oracleConnectionStr))
            {
                conn.Open();
                using (OracleCommand command = conn.CreateCommand())
                {
                    command.CommandText = sql;
                    command.Parameters.AddRange(paramList);
                    DataTable dt = new DataTable();
                    OracleDataAdapter adapter = new OracleDataAdapter(command);
                    adapter.Fill(dt);
                    return dt;
                }
            }
        }

        public static int ExecuteNonQuery(string sql, params OracleParameter[] paramList)
        {
            using (OracleConnection conn = new OracleConnection(oracleConnectionStr))
            {
                conn.Open();
                using (OracleCommand command = conn.CreateCommand())
                {
                    command.CommandText = sql;
                    command.Parameters.AddRange(paramList);
                    return command.ExecuteNonQuery();
                }
            }
        }

        public static object ExecuteScalar(string sql, params OracleParameter[] paramList)
        {
            using (OracleConnection conn = new OracleConnection(oracleConnectionStr))
            {
                conn.Open();
                using (OracleCommand command = conn.CreateCommand())
                {
                    command.CommandText = sql;
                    command.Parameters.AddRange(paramList);
                    return command.ExecuteScalar();
                }
            }
        }
    }

 #>

在vs2019中保存*.tt文件的时候会自动提示运行。

技术图片

 

 

OracleClient

以上是关于在.Net Core中使用T4工具生成实体文件的主要内容,如果未能解决你的问题,请参考以下文章

T4 模板自动生成带注释的实体类文件 - 只需要一个 SqlSugar.dll

无需任何配置即可生成实体代码的 T4 模板

t4 根据表名数组生成实体

.NET使用一行命令轻松生成EF Core项目框架

为什么使用T4修改EF中的实体?

使用 t4 模板生成动态代码