使用T4模板动态生成NPoco实体类

这是一个妥妥的NPoco类,这是我们在工作开发中,手动去写这个实体类,属实非常心累,字段少无所谓一次两次,数量多了,字段多了,就心态裂开🙄


今天分享一下如何使用T4模板生成实体类

using System;
using NPoco;
using System.ComponentModel.DataAnnotations;

namespace Electric.Domain.Entities 
{
   /// <summary>
/// Represents a T_RepairParts.
/// NOTE: 这个类是从T4模板生成的——你不应该手动修改它。
/// </summary>
[MetadataType(typeof(T_RepairPartsMetadata))]
[PrimaryKey("ID")]
[TableName("[dbo].[T_RepairParts]")]
public class T_RepairParts 
{
	#region ResultColumn
	#endregion
	#region Ignore
	#endregion
	
	private class T_RepairPartsMetadata{
	
		[StringLength(4, ErrorMessage = "{0}不能超过4个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "")]
		[Column("ID")]
		public int Id { get; set; }

		[StringLength(50, ErrorMessage = "{0}不能超过50个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "配件名称")]
		[Column("PartsName")]
		public string PartsName { get; set; }

		[StringLength(100, ErrorMessage = "{0}不能超过100个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "绑定品牌")]
		[Column("RelationBrands")]
		public string RelationBrands { get; set; }

		[StringLength(100, ErrorMessage = "{0}不能超过100个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "关联维修")]
		[Column("RelationMaintainers")]
		public string RelationMaintainers { get; set; }

		[StringLength(100, ErrorMessage = "{0}不能超过100个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "关联车系")]
		[Column("RelationVehicleSeries")]
		public string RelationVehicleSeries { get; set; }

		[StringLength(-1, ErrorMessage = "{0}不能超过-1个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "")]
		[Column("EditorContent")]
		public string EditorContent { get; set; }

		[StringLength(-1, ErrorMessage = "{0}不能超过-1个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "")]
		[Column("BasicDetails")]
		public string BasicDetails { get; set; }

		[StringLength(8, ErrorMessage = "{0}不能超过8个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "创建时间")]
		[Column("CreateTime")]
		public DateTime CreateTime { get; set; }

		
		
		[Display(Name = "修改时间")]
		[Column("Updatetime")]
		public DateTime? Updatetime { get; set; }

		[StringLength(1, ErrorMessage = "{0}不能超过1个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "是否删除")]
		[Column("IsDel")]
		public bool IsDel { get; set; }

		[StringLength(200, ErrorMessage = "{0}不能超过200个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "配件标签")]
		[Column("Tips")]
		public string Tips { get; set; }

		[StringLength(9, ErrorMessage = "{0}不能超过9个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "人工价")]
		[Column("LaborPrice")]
		public decimal LaborPrice { get; set; }

		[StringLength(9, ErrorMessage = "{0}不能超过9个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "配件价")]
		[Column("PartsPrice")]
		public decimal PartsPrice { get; set; }

		[StringLength(9, ErrorMessage = "{0}不能超过9个字符!")]
		[Required(ErrorMessage = "请填写{0}!")]
		[Display(Name = "门店市场价格")]
		[Column("StorePrice")]
		public decimal StorePrice { get; set; }

	}
  }      
}

模板是搬运国外一个大神博客内的代码,下面换个模板是我改后增强的
支持生成字段注释,支持生成字段可空,支持生成字段长度,我并且按照我自己的项目类结构重新弄了一下,原版的T4代码我也分享出来,可以看看

帮助文章: https://www.davidhaney.io/automatically-generate-pocos-from-db-with-t4/

我改后的-T4模板代码

<#@ template language="C#" hostspecific="true" debug="True" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>

<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Configuration" #>
<#@ assembly name="Microsoft.SqlServer.Smo" #>
<#@ assembly name="Microsoft.SqlServer.ConnectionInfo" #>
<#@ assembly name="Microsoft.SqlServer.Management.Sdk.Sfc" #>

<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="Microsoft.SqlServer.Management.Smo" #>
 
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Data.SqlClient" #>
<#

    var configurationFileMap = new ExeConfigurationFileMap();
    configurationFileMap.ExeConfigFilename = this.Host.ResolvePath("App.config");
    var config = ConfigurationManager.OpenMappedExeConfiguration(configurationFileMap, ConfigurationUserLevel.None);

    //**********************************************************************************************
    // This T4 generates POCOs from the specified DB and saves them to the specified folder which 
    // is relative to the template's location. One file per table/POCO.
    //**********************************************************************************************
    //****************************
    // DEFINE YOUR VARIABLES HERE
    //****************************
    // The SQL server name or IP
    string sqlServer = config.AppSettings.Settings["sqlServer"].Value;
    // The SQL username
    string sqlLogin = config.AppSettings.Settings["sqlLogin"].Value;
    // The SQL password
    string sqlPassword = config.AppSettings.Settings["sqlPassword"].Value;
    // The SQL database to generate the POCOs for
    string sqlDatabase = config.AppSettings.Settings["sqlDatabase"].Value;
    // The namespace to apply to the generated classes
    string classNamespace = config.AppSettings.Settings["classNamespace"].Value;
    // The destination folder for the generated classes, relative to this file's location.
    string destinationFolder = config.AppSettings.Settings["destinationFolder"].Value;
    // Loop over each table and create a class file!
    Server server = new Server(sqlServer);
    server.ConnectionContext.LoginSecure = false;
    server.ConnectionContext.Login = sqlLogin;
    server.ConnectionContext.Password = sqlPassword;
    server.ConnectionContext.Connect();
    foreach (Table table in server.Databases[sqlDatabase].Tables)
    {
        // Skip sys tables
        if (table.Name.StartsWith("sys"))
        {
            continue;
        }

		string nombreTabla="["+ table.Schema +"].["+table.Name+"]";
		
		//search PK
		String namePK="";
		foreach (Column col in table.Columns)
        {
			if(col.InPrimaryKey){
				namePK=col.Name;
				continue;
			}
		}

		String nameSchema="";
		if(!table.Schema.Equals("dbo")){
			nameSchema = "."+table.Schema;
		}

#>
using System;
using NPoco;
using System.ComponentModel.DataAnnotations;

namespace <#= classNamespace #><#= nameSchema #> 
{
    /// <summary>
    /// Represents a <#= table.Name #>.
    /// NOTE: 这个类是从T4模板生成的——你不应该手动修改它。
    /// </summary>
	[MetadataType(typeof(<#=table.Name + "Metadata"#>))]
	[PrimaryKey("<#= namePK #>")]
	[TableName("<#= nombreTabla #>")]
    public class <#= table.Name #> 
    {
	    #region ResultColumn
        #endregion
        #region Ignore
        #endregion
		
		private class <#=table.Name + "Metadata"#>{
<# 
        // Keep count so we don't whitespace the last property/column
        int columnCount = table.Columns.Count;
        int i = 0;
        // Iterate all columns
        foreach (Column col in table.Columns)
        {
            i++;
            string propertyType = GetNetDataType(col.DataType.Name);
            // If we can't map it, skip it
            if (string.IsNullOrWhiteSpace(propertyType))
            {
                // Skip
                continue;
            }
			string strLength = string.Empty;
			string remark = GetRemark(col.Name,nombreTabla,config.AppSettings);
			string strNullable = string.Empty;
            // Handle nullable columns by making the type nullable
            if (col.Nullable && propertyType != "string")
            {
                propertyType += "?";
            }else{
				strLength = "[StringLength(" + col.DataType.MaximumLength +", ErrorMessage = \"{0}不能超过"+col.DataType.MaximumLength+"个字符!\")]";
			}

            if (!col.Nullable)
            {
			    strNullable = "[Required(ErrorMessage = \"请填写{0}!\")]";
            }

			String nameColumn="Id";
			String nameColumnNPoco=col.Name;

			if(!col.InPrimaryKey){
				nameColumn=FirstCharToUpper(col.Name);
			}
#>
			<#=strLength#>
			<#=strNullable#>
			[Display(Name = "<#=remark#>")]
			[Column("<#= nameColumnNPoco #>")]
			public <#= propertyType #> <#= nameColumn #> { get; set; }

<#
            // Do we insert the space?
            if (i != columnCount)
            {
#>
<#
            }
#>
<#
        }
#>
    }
  }      
}
<#
        // Write new POCO class to its own file
        SaveOutput(table.Name + ".cs", destinationFolder);
    } 
#>
<#+
    public static string GetNetDataType(string sqlDataTypeName)
    {
        switch (sqlDataTypeName.ToLower())
        {
            case "bigint":
                return "Int64";
            case "binary":
            case "image":
            case "varbinary":
                return "byte[]";
            case "bit":
                return "bool";
            case "char":
                return "char";
            case "datetime":
            case "smalldatetime":
                return "DateTime";
            case "decimal":
            case "money":
            case "numeric":
                return "decimal";
            case "float":
                return "double";
            case "int":
                return "int";
            case "nchar":
            case "nvarchar":
            case "text":
            case "varchar":
            case "xml":
                return "string";
            case "real":
                return "single";
            case "smallint":
                return "Int16";
            case "tinyint":
                return "byte";
            case "uniqueidentifier":
                return "Guid";
            default:
                return null;
        }
    }

	//码农disco修改版,支持字段注释
	public static string GetRemark(string name,string table,AppSettingsSection config)
	{
		string result = string.Empty;
        if (table == "[dbo].[T_RepairParts]" && name!="ID")
        {
		 
        }
		string sqlServer = config.Settings["sqlServer"].Value;
		string sqlLogin = config.Settings["sqlLogin"].Value;
		string sqlPassword = config.Settings["sqlPassword"].Value;
		string sqlDatabase = config.Settings["sqlDatabase"].Value;

		string connString = "Server="+ sqlServer +";DataBase="+sqlDatabase+";Uid="+sqlLogin+";Pwd="+sqlPassword;
        SqlConnection conn = new SqlConnection(connString);

        string sql = string.Format(@"							USE electric2014
							SELECT  
A.name AS table_name,  
B.name AS column_name,  
C.value AS column_description  
FROM sys.tables A  
INNER JOIN sys.columns B ON B.object_id = A.object_id  
LEFT JOIN sys.extended_properties C ON C.major_id = B.object_id AND C.minor_id = B.column_id  
WHERE A.name = '{0}'  AND B.name = '{1}' ",table.Replace("dbo","").Replace("[","").Replace("]","").Replace(".",""),name);
        SqlCommand cmd = new SqlCommand(sql, conn);
        conn.Open();
        SqlDataReader  dr = cmd.ExecuteReader();
		while(dr.Read())
		{
		   result = dr["column_description"].ToString();
		}
        conn.Close();
		return result;
	}

	public static string FirstCharToUpper(string input)
	{
		if (String.IsNullOrEmpty(input))
			throw new ArgumentException("ARGH!");
		return input.First().ToString().ToUpper() + input.Substring(1);
	}

    void SaveOutput(string outputFileName, string destinationFolder)
    {
        // Write to destination folder
        string templateDirectory = Path.Combine(Path.GetDirectoryName(Host.TemplateFile), destinationFolder);
        string outputFilePath = Path.Combine(templateDirectory, outputFileName);
        File.Delete(outputFilePath);
        File.WriteAllText(outputFilePath, this.GenerationEnvironment.ToString()); 
        // Flush generation
        this.GenerationEnvironment.Remove(0, this.GenerationEnvironment.Length);
    }
#>

所有表生成的类都会写到Export内,这下美滋滋了!🌈

项目源代码下载:github
代码最好拉取Git上的,因为博客的这个代码,可能后面不会再更新了

posted @ 2020-06-17 09:53  Homegu  阅读(522)  评论(1编辑  收藏  举报