T4 代码生成 Demo (抽奖程序)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了T4 代码生成 Demo (抽奖程序)相关的知识,希望对你有一定的参考价值。

 

参考自这位大狮的:  https://github.com/Pencroff/Dapper-DAL/blob/master/Dapper-DAL/Models/ModelGenerator.tt

项目Demo下载 http://download.csdn.net/detail/qq_21533697/9904071       

  • 支持Oracle,MSSQL,SQLite   
  • Demo项目是个抽奖小程序,抽奖只用到了LuckDraw表
  • 用的SQLite包含库方便直接运行
  • 里面用到Dapper就只写了Model层的模板, 

 


 

文件目录

 技术分享

 


 

T4库

表结构读取抽象类  SchemaReader.ttinclude  

技术分享
  1 <#+ 
  2 /*
  3 The contents of this file are subject to the New BSD
  4  License (the "License"); you may not use this file
  5  except in compliance with the License. You may obtain a copy of
  6  the License at http://www.opensource.org/licenses/bsd-license.php
  7  
  8  Software distributed under the License is distributed on an 
  9  "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 10  implied. See the License for the specific language governing
 11  rights and limitations under the License.
 12 */
 13 
 14 string ConnectionString = ""; 
 15 string TableFilter = ""; 
 16 string TopNamespace = "";
 17 string Namespace = "";
 18 string ClassPrefix = "";
 19 string ClassSuffix = "";
 20 string SchemaName = null;
 21 bool IncludeViews;
 22 string[] ExcludeTablePrefixes = new string[]{};
 23 string _connectionString="";
 24 string _providerName="";
 25 
 26 static Regex rxCleanUp = new Regex(@"[^\\w\\d_]", RegexOptions.Compiled);
 27 
 28 static Func<string, string> CleanUp = (str) =>
 29 {
 30     str = rxCleanUp.Replace(str, "_");
 31     if (char.IsDigit(str[0])) str = "_" + str;
 32     
 33     return str;
 34 };
 35 
 36 string CheckNullable(Column col)
 37 {
 38     string result="";
 39     if(col.IsNullable && 
 40         col.PropertyType !="byte[]" && 
 41         col.PropertyType !="string" &&
 42         col.PropertyType !="Microsoft.SqlServer.Types.SqlGeography" &&
 43         col.PropertyType !="Microsoft.SqlServer.Types.SqlGeometry"
 44         )
 45         result="?";
 46     return result;
 47 }
 48   
 49 static bool IsExcluded(string tablename, string[] ExcludeTablePrefixes)
 50 {
 51     for (int i = 0; i < ExcludeTablePrefixes.Length; i++)
 52     {
 53         string s = ExcludeTablePrefixes[i];
 54         if(tablename.StartsWith(s)) return true;
 55     }
 56     return false;
 57 }
 58 
 59 
 60 abstract class SchemaReader
 61 {
 62     public abstract Tables ReadSchema(string connstr, string tableFilter);
 63     public GeneratedTextTransformation outer;
 64     public void WriteLine(string o)
 65     {
 66         outer.WriteLine(o);
 67     }
 68     
 69     public string GetPropertyType(string sqlType)
 70     { 
 71         string sysType = "string";
 72         switch (sqlType)
 73         {
 74             case "bigint":
 75                 sysType = "long";
 76                 break;
 77             case "smallint":
 78                 sysType = "short";
 79                 break;
 80             case "int":
 81             case "number":
 82             case "integer":
 83                 sysType = "int";
 84                 break;
 85             case "uniqueidentifier":
 86                 sysType = "Guid";
 87                 break;
 88             case "smalldatetime":
 89             case "datetime":
 90             case "date":
 91             case "time":
 92                 sysType = "DateTime";
 93                 break;
 94             case "float":
 95                 sysType = "double";
 96                 break;
 97             case "real":
 98                 sysType = "float";
 99                 break;
100             case "numeric":
101             case "smallmoney":
102             case "decimal":
103             case "money":
104                 sysType = "decimal";
105                 break;
106             case "tinyint":
107                 sysType = "byte";
108                 break;
109             case "bit":
110                 sysType = "bool";
111                 break;
112             case "image":
113             case "binary":
114             case "varbinary":
115             case "timestamp":
116                 sysType = "byte[]";
117                 break;
118             case "geography":
119                 sysType = "Microsoft.SqlServer.Types.SqlGeography";
120                 break;
121             case "geometry":
122                 sysType = "Microsoft.SqlServer.Types.SqlGeometry";
123                 break;
124         }
125         return sysType;
126     }
127 } 
128  
129 public class Table
130 {
131     public List<Column> Columns;    
132     public string Name;
133     public string Schema;
134     public bool IsView;
135     public string CleanName;
136     public string ClassName;
137     public string SequenceName;
138     public bool Ignore;
139 
140     public Column PK
141     {
142         get
143         {
144             return this.Columns.SingleOrDefault(x=>x.IsPK);
145         }
146     }
147 
148     public Column GetColumn(string columnName)
149     {
150         return Columns.Single(x=>string.Compare(x.Name, columnName, true)==0);
151     }
152 
153     public Column this[string columnName]
154     {
155         get
156         {
157             return GetColumn(columnName);
158         }
159     }
160 
161 }
162 
163 public class Column
164 {
165     public string Name;
166     public string PropertyName;
167     public string PropertyType;
168     public string DbType;
169     public bool IsPK;
170     public bool IsNullable;
171     public bool IsAutoIncrement;
172     public bool Ignore;
173 }
174 
175 public class Tables : List<Table>
176 {
177     public Tables()
178     {
179     }
180     
181     public Table GetTable(string tableName)
182     {
183         return this.Single(x=>string.Compare(x.Name, tableName, true)==0);
184     }
185 
186     public Table this[string tableName]
187     {
188         get
189         {
190             return GetTable(tableName);
191         }
192     }
193 
194 }
195  
196 #>

SQLite表结构读取实现 SQLiteSchemaReader.ttinclude  

技术分享
  1 <#@ include file=".\\SchemaReader.ttinclude" #>
  2 <#+  
  3 Tables LoadTables()
  4 { 
  5 
  6     WriteLine("// This file was automatically generated by the Dapper.SimpleCRUD T4 Template");
  7     WriteLine("// Do not make changes directly to this file - edit the template instead");
  8     WriteLine("// ");
  9     WriteLine("// The following connection settings were used to generate this file");
 10     WriteLine("// ");
 11     WriteLine("//     Connection String : `{0}`", ConnectionString); 
 12     WriteLine("");
 13 
 14     //DbProviderFactory _factory ;
 15     try
 16     {
 17         // _factory = DbProviderFactories.GetFactory(ProviderName);
 18     }
 19     catch (Exception x)
 20     {
 21         var error=x.Message.Replace("\\r\\n", "\\n").Replace("\\n", " ");
 22         WriteLine("");
 23         WriteLine("// -----------------------------------------------------------------------------------------");
 24         WriteLine("// -----------------------------------------------------------------------------------------");
 25         WriteLine("");
 26         return new Tables();
 27     }
 28 
 29     try
 30     {
 31         Tables result;
 32         
 33         SchemaReader reader= new SqliteSchemaReader();
 34         result=reader.ReadSchema(ConnectionString, TableFilter);
 35         
 36         for (int i=result.Count-1; i>=0; i--)
 37         {
 38             if (SchemaName!=null && string.Compare(result[i].Schema, SchemaName, true)!=0)
 39             {
 40                 result.RemoveAt(i);
 41                 continue;
 42             }
 43             if (!IncludeViews && result[i].IsView)
 44             {
 45                 result.RemoveAt(i);
 46                 continue;
 47             }
 48         }
 49 
 50         
 51 
 52         var rxClean = new Regex("^(Equals|GetHashCode|GetType|ToString|repo|Save|IsNew|Insert|Update|Delete|Exists|SingleOrDefault|Single|First|FirstOrDefault|Fetch|Page|Query)$");
 53         foreach (var t in result)
 54         {
 55             t.ClassName = ClassPrefix + t.ClassName + ClassSuffix;
 56             foreach (var c in t.Columns)
 57             {
 58                 c.PropertyName = rxClean.Replace(c.PropertyName, "_$1");
 59 
 60                 // Make sure property name doesn‘t clash with class name
 61                 if (c.PropertyName == t.ClassName)
 62                     c.PropertyName = "_" + c.PropertyName;
 63             }
 64         }
 65 
 66             return result;
 67     }
 68     catch (Exception x)
 69     {
 70         var error=x.Message.Replace("\\r\\n", "\\n").Replace("\\n", " ");
 71         Warning(string.Format("Failed to read database schema - {0}", error));
 72         WriteLine("");
 73         WriteLine("// -----------------------------------------------------------------------------------------");
 74         WriteLine("// Failed to read database schema - {0}", error);
 75         WriteLine("// -----------------------------------------------------------------------------------------");
 76         WriteLine("");
 77         return new Tables();
 78     }
 79 
 80         
 81 }
 82 
 83 class SqliteSchemaReader : SchemaReader
 84     {
 85          
 86         private    string _connstr {get;set;}
 87 
 88         public override Tables ReadSchema(string connstr, string tableFilter)
 89         { 
 90             _connstr = connstr;
 91             var result = new Tables(); 
 92             //pull the tables in a reader 
 93             using (IDataReader rdr = ExecuteReader(TABLE_SQL + tableFilter)) // SQLitehelper.
 94             {
 95                 while (rdr.Read())
 96                 {
 97                     Table tbl = new Table();
 98                     tbl.Name = rdr["name"].ToString();
 99                     //tbl.Schema = rdr["TABLE_SCHEMA"].ToString();
100                     //tbl.IsView = string.Compare(rdr["TABLE_TYPE"].ToString(), "View", true) == 0;
101                     tbl.CleanName = CleanUp(tbl.Name);
102                     // tbl.CleanName = T4Generator.CleanUp(tbl.Name);
103                     if (tbl.CleanName.StartsWith("tbl_")) tbl.CleanName = tbl.CleanName.Replace("tbl_", "");
104                     if (tbl.CleanName.StartsWith("tbl")) tbl.CleanName = tbl.CleanName.Replace("tbl", "");
105                     tbl.CleanName = tbl.CleanName.Replace("_", "");
106                     tbl.ClassName = tbl.CleanName;
107 
108                     result.Add(tbl);
109                 }
110            } 
111 
112             foreach (var tbl in result)
113             {
114                 tbl.Columns = LoadColumns(tbl);
115 
116                 //Mark the primary key
117                 //string PrimaryKey = GetPK(tbl.Schema, tbl.Name);
118                 //var pkColumn = tbl.Columns.SingleOrDefault(x => x.Name.ToLower().Trim() == PrimaryKey.ToLower().Trim());
119                 //if (pkColumn != null)
120                 //{
121                 //    pkColumn.IsPK = true;
122                 //}
123             }
124 
125 
126             return result;
127         }
128 
129         List<Column> LoadColumns(Table tbl)
130         {
131             var result = new List<Column>();
132             using (IDataReader rdr = ExecuteReader(COLUMN_SQL.Replace("@tableName", tbl.Name))) // SQLitehelper.
133             {
134                 while (rdr.Read())
135                 {
136                     Column col = new Column();
137                     col.Name = rdr["name"].ToString();
138                     col.PropertyName = CleanUp(col.Name);
139                     //col.PropertyName = T4Generator.CleanUp(col.Name);
140                     col.PropertyType = base.GetPropertyType(rdr["type"].ToString().ToLower());
141                     col.IsNullable = rdr["notnull"].ToString() != "1";
142                     //col.IsAutoIncrement = false; //((int)rdr["IsIdentity"]) == 1;
143                     col.IsPK = rdr["pk"].ToString() == "1";
144                     result.Add(col);
145                 }
146             }
147 
148             return result;
149         }
150         
151         string Table_Filter =  " ";
152 
153         const string TABLE_SQL = " select name from sqlite_master where type = ‘table‘ ";
154 
155         const string COLUMN_SQL = " PRAGMA table_info(@tableName) ";
156         
157         /// <summary>
158         /// 查询
159         /// </summary>
160         /// <param name="sql">sql语句</param>
161         /// <param name="slPars">参数</param>
162         /// <returns>发挥SQLiteDataReader</returns>
163         public SQLiteDataReader ExecuteReader(string sql, params SQLiteParameter[] slPars)
164         {
165             SQLiteConnection conn = new SQLiteConnection(_connstr);
166             using (SQLiteCommand cmd = new SQLiteCommand(sql,conn))
167             {
168                 if (slPars != null)
169                 {
170                     cmd.Parameters.AddRange(slPars);
171                 } 
172                 try
173                 {
174                     conn.Open();
175                     return cmd.ExecuteReader(CommandBehavior.CloseConnection);
176                 }
177                 catch(Exception ex)
178                 {
179                     conn.Close();
180                     conn.Dispose();
181                     throw ex;
182                 }
183 
184             }
185 
186         }
187 
188     } 
189 #>

SQLite配置文件  SQLiteInit.ttinclude    

1.配置连接串   2.需要生成的表  3.顶级命名空间

4.一个库对应一个配置文件  (开始是把这些配置直接写在各层模板文件的,后来涉及多库的切换,每个文件改链接麻烦)
5. 注意修改连接串为自己对应的  ConnectionString = @"Data Source=E:/cc/test/LotterySite/Lib/db/cater.db;"; 

 1 <#@ include file="./SQLiteSchemaReader.ttinclude" #>
 2 <#  // 初始化文件 一个库对应一个ttinclude文件 
 3     // Settings  初始化配置 
 4     ConnectionString = @"Data Source=E:/cc/test/LotterySite/Lib/db/cater.db;";  // 连接串
 5     TableFilter = " and name in (‘LuckDraw‘) ";  // 过滤表
 6     TopNamespace = "FW";  // 顶级命名空间
 7     ClassPrefix = ""; 
 8     ClassSuffix = "";
 9     IncludeViews = true;
10     ExcludeTablePrefixes = new string[]{"aspnet_","webpages_"}; 
11     
12     // Read schema
13     var tables = LoadTables();   //读取的所有表结构
14 #>

 


 

SQLite 模板使用 

 1 <#@ template hostspecific="True" #>
 2 <#@ include file="EF.Utility.CS.ttinclude"#> 
 3 <#@ include file="$(SolutionDir)\\FW.Common\\T4Ttinclude\\SQLiteInit.ttinclude" #>
 4 <#@ assembly name="EnvDTE" #>
 5 <#@ assembly name="System.Data" #>
 6 <#@ assembly name="System.Data.Entity.Design" #>
 7 <#@ assembly name="System.Xml" #>
 8 <#@ assembly name="System.Configuration" #>
 9 <#@ assembly name="$(SolutionDir)\\Lib\\sqlite\\System.Data.SQLite.dll" #> 
10 
11 <#@ import namespace="System.Collections.Generic" #>
12 <#@ import namespace="System.Data" #>
13 <#@ import namespace="System.Data.Common" #>
14 <#@ import namespace="System.Diagnostics" #>
15 <#@ import namespace="System.Globalization" #>
16 <#@ import namespace="System.IO" #>
17 <#@ import namespace="System.Linq" #>
18 <#@ import namespace="System.Text" #>
19 <#@ import namespace="System.Text.RegularExpressions" #>
20 <#@ import namespace="System.Configuration" #>
21 <#@ import namespace="System.Data.SQLite" #>
22 <#@ output extension=".cst"#>  
23 
24 
25 <# 
26     Namespace = TopNamespace + ".TestModel";
27     // Read schema 
28     
29     EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this); // 多文件生成
30 /*
31     // Tweak Schema
32     tables["tablename"].Ignore = true;                            // To ignore a table
33     tables["tablename"].ClassName = "newname";                    // To change the class name of a table
34     tables["tablename"]["columnname"].Ignore = true;            // To ignore a column
35     tables["tablename"]["columnname"].PropertyName="newname";    // To change the property name of a column
36     tables["tablename"]["columnname"].PropertyType="bool";        // To change the property type of a column
37 */
38 #>
39 
40 <# fileManager.StartHeader(); #>
41 
42 using System;
43 using Dapper;
44 using Dapper.Contrib.Extensions;
45 
46 namespace <#=Namespace #>
47 {
48 
49 <# fileManager.EndBlock(); #>
50 
51 
52 <#
53 foreach(Table tbl in from t in tables where !t.Ignore select t){
54         if(IsExcluded(tbl.Name, ExcludeTablePrefixes)) continue;
55          
56         fileManager.StartNewFile(tbl.Name+".cs"); // 新建文件
57 #>
58     /// <summary>
59     /// A class which represents the <#=tbl.Name#> <#=(tbl.IsView)?"view":"table"#>.
60     /// </summary>
61     [Table("[<#=tbl.Name#>]")]
62     public partial class <#=tbl.ClassName#>
63     {
64        /* <#foreach(Column col in from c in tbl.Columns where !c.Ignore select c) {#> <#=col.PropertyName #> <#}#> */ 
65 
66 <#foreach(Column col in from c in tbl.Columns where !c.Ignore select c)
67 {#>
68     <# if (tbl.PK!=null && tbl.PK.Name==col.PropertyName) { #>
69     [Key]
70     <#}#>
71     public virtual <#=col.PropertyType #><#=CheckNullable(col)#> <#=col.PropertyName #> { get; set; }
72 <#}#>
73     }
74 
75 <#}#>
76 
77 <# fileManager.StartFooter(); #>
78 } // namespace
79 <# fileManager.EndBlock(); #>
80 <# fileManager.Process(true); #> 
81  

模板属性:

Namespace 命名空间
tables 表结构集合

表属性 
Name 数据库中的表名
ClassName 实体类名称
IsView 是否是视图(没怎么用)
PK.Name 主键列名

列属性
PropertyName 属性名称
PropertyType 属性类型
CheckNullable(col) 可空类型判断

 

注意引入对应的SQLite的T4配置库   

<#@ include file="$(SolutionDir)\\FW.Common\\T4Ttinclude\\SQLiteInit.ttinclude" #>

$(SolutionDir)         解决方案目录 

 

以上是关于T4 代码生成 Demo (抽奖程序)的主要内容,如果未能解决你的问题,请参考以下文章

T4模板之菜菜鸟篇

原生弹窗拖拽代码demo+简单的抽奖

幸运大转盘-jQuery+PHP实现的抽奖程序

T4模板学习心得

iOS 抽奖轮盘跑马灯边框的实现

分享一些经典的特效效果,希望对大家有帮助