因爲最近公司在用webform開發ERP,用到大量重複機械的代碼,以前寫了篇文章,懶人小工具:自動生成Model,Insert,Select,Delete以及導出Excel的方法,可是有人以爲這種方法很麻煩。其實我感受確實是有點麻煩,麻煩在於字符串的拼接。
這種時候我想到了T4模板,用過EF的 DatabaseFirst自動生成實體的同窗就明白,dbfirst 自帶T4模板,以前咱們在學習spring.net框架的時候,也有用過T4模板根據數映射到實體類自動建立倉儲。T4模板其實還有不少應用的場景。
T4模板確實挺方便的,可是其實其中用過的原理和我以前作winform小工具差很少。都是根據數據字段和類型的映射生成實體。另外就是ado.net基礎知識。
可是這種方法你得了解T4模板的基礎語法。各有利弊,可是其實語法也不是很難. html
先預覽下擴展的界面,winform程序就不在意美觀不美觀了...git
如今添加了安裝包,直接點擊下一步就能夠了,在桌面生成快捷方式,點擊可用。github
1 <#@ template language="C#" debug="True" hostspecific="True" #> 2 <#@ output extension=".cs" #> 3 <#@ assembly name="System.Data" #> 4 <#@ assembly name="System.xml" #> 5 <#@ import namespace="System.Collections.Generic" #> 6 <#@ import namespace="System.Data.SqlClient" #> 7 <#@ import namespace="System.Data" #> 8 using System.Collections.Generic; 9 using System.Linq; 10 using System.Text; 11 using System.Text.RegularExpressions; 12 using System.Windows.Forms; 13 using System.Data; 14 using CMS.Utilities; 15 using System.Data.OleDb; 16 using System.Configuration; 17 using System.Data.SqlClient; 18 using System; 19 namespace MyProject.Entities 20 { 21 <# 22 string connectionString = "server=.;database=databasename;uid=uid;pwd=123456"; 23 string selectQuery = "select * from Team_"; 24 string tableName="Team_"; 25 SqlConnection conn = new SqlConnection(connectionString); 26 conn.Open(); 27 System.Data.DataTable schema = null; 28 SqlCommand selectcommand = new SqlCommand(selectQuery, conn); 29 SqlDataAdapter sda = new SqlDataAdapter(selectcommand); 30 System.Data.DataSet dss = new System.Data.DataSet(); 31 sda.Fill(dss); 32 schema=dss.Tables[0]; 33 System.Data.DataTable dt = dss.Tables[0]; 34 System.Data.DataRow dr = dss.Tables[0].Rows[0]; 35 SqlCommand command = new SqlCommand(selectQuery,conn); 36 SqlDataAdapter ad = new SqlDataAdapter(command); 37 38 #> 39 public class <#= tableName#>Biz 40 { 41 public class <#= tableName#>Model 42 { 43 <# foreach (DataColumn dc in dss.Tables[0].Columns) 44 { #> 45 private <#= dc.DataType.Name #> _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #>; 46 public <#= dc.DataType.Name #> <#= dc.ColumnName #> 47 { 48 get { return _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #>; } 49 set { _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #> = value; } 50 } 51 <# } #> 52 53 } 54 55 56 } 57 58 }
這種方式是挺簡單的。<#@ import namespace="System.Data" #>這段代碼是引用命名空間,在你後臺代碼中用,也就是包括下面ado.net中須要引用的命名空間,基本都寫在這裏。用 <#...dosomething...#>這段就是不用展現出來的代碼,其餘的代碼就是在你用T4模板生成的時候要用的代碼。是否是很簡單。上面的代碼無需詳細解釋了吧,運用ado.net連接數據庫,獲取表字段和類型。Ctrl+S就自動生成了實體類。web
根據模板生成的Modelspring
1 using System.Collections.Generic; 2 using System.Linq; 3 using System.Text; 4 using System.Text.RegularExpressions; 5 using System.Windows.Forms; 6 using System.Data; 7 using CMS.Utilities; 8 using System.Data.OleDb; 9 using System.Configuration; 10 using System.Data.SqlClient; 11 using System; 12 namespace MyProject.Entities 13 { 14 15 public class Team_Biz 16 { 17 public class Team_Model 18 { 19 20 private String _team_code; 21 public String Team_code 22 { 23 get { return _team_code; } 24 set { _team_code = value; } 25 } 26 27 private String _team_name; 28 public String Team_name 29 { 30 get { return _team_name; } 31 set { _team_name = value; } 32 } 33 34 private String _team_status; 35 public String Team_status 36 { 37 get { return _team_status; } 38 set { _team_status = value; } 39 } 40 41 private String _team_user; 42 public String Team_user 43 { 44 get { return _team_user; } 45 set { _team_user = value; } 46 } 47 48 private DateTime _team_date; 49 public DateTime Team_date 50 { 51 get { return _team_date; } 52 set { _team_date = value; } 53 } 54 } 55 56 } 57 58 }
1 <#@ template language="C#" debug="True" hostspecific="True" #> 2 3 <#@ assembly name="System.Data" #> 4 5 <#@ assembly name="System.xml" #> 6 7 <#@ import namespace="System.Collections.Generic" #> 8 9 <#@ import namespace="System.Data.SqlClient" #> 10 11 <#@ import namespace="System.Data" #> 12 13 <#@ output extension=".cs" #> 14 15 using System; 16 17 namespace Test.T4 18 19 { 20 21 <# 22 23 string connectionString="data source=(local);initial catalog=musicstore;user id=sa;password=123456;"; 24 25 SqlConnection conn = new SqlConnection(connectionString); 26 27 conn.Open(); 28 29 DataTable schema = conn.GetSchema("TABLES"); 30 31 string strSql = "select * from @tableName"; 32 33 SqlCommand command = new SqlCommand(strSql,conn); 34 35 SqlDataAdapter ad = new SqlDataAdapter(command); 36 37 DataSet ds = new DataSet(); 38 39 foreach(DataRow row in schema.Rows) 40 41 { #> 42 43 public class <#= row["TABLE_NAME"].ToString().Trim() #> 44 45 { <# 46 47 ds.Tables.Clear(); 48 49 command.CommandText = strSql.Replace("@tableName",row["TABLE_NAME"].ToString()); 50 51 ad.FillSchema(ds, SchemaType.Mapped, row["TABLE_NAME"].ToString()); 52 53 foreach (DataColumn dc in ds.Tables[0].Columns) 54 55 { #> 56 public <#= dc.DataType.Name #> <#= dc.ColumnName #> { get; set; } 57 <# } #> 58 } 59 60 <# 61 62 } #> 63 <# conn.Close(); #> 64 }
DataTable schema = conn.GetSchema("TABLES");是獲取數據庫全部表名,而後遍歷全部表名遍歷表字段和類型,根據這些表生成實體。
另外還有一種方法是用數據存儲過程自動生成實體。這種方法就須要SQL的基礎知識了。sql
1 SET ANSI_NULLS ON; 2 SET QUOTED_IDENTIFIER ON; 3 GO 4 5 CREATE PROC [dbo].[p_db_wsp] 6 @dbname VARCHAR(50) , --數據庫名 7 @path VARCHAR(100) , --實體類所在目錄名,如D:/My/Models 8 @namespace VARCHAR(50) --實體類命名空間,默認值爲Models 9 AS --判斷數據庫是否存在 10 IF ( DB_ID(@dbname) IS NOT NULL ) 11 BEGIN 12 IF ( ISNULL(@namespace, '') = '' ) 13 SET @namespace = 'Models'; 14 -- 容許配置高級選項 15 EXEC sp_configure 'show advanced options', 1; 16 -- 從新配置 17 RECONFIGURE; 18 -- 啓用Ole Automation Procedures 19 EXEC sp_configure 'Ole Automation Procedures', 1; 20 -- 啓用xp_cmdshell,能夠向磁盤中寫入文件 21 EXEC sp_configure 'xp_cmdshell', 1; 22 -- 從新配置 23 RECONFIGURE; 24 DECLARE @dbsql VARCHAR(1000) , 25 @tablename VARCHAR(100); 26 SET @dbsql = 'declare wsp cursor for select name from ' + @dbname 27 + '..sysobjects where xtype=''u'' and name <>''sysdiagrams'''; 28 EXEC(@dbsql); 29 OPEN wsp; 30 FETCH wsp INTO @tablename;--使用遊標循環遍歷數據庫中每一個表 31 WHILE ( @@fetch_status = 0 ) 32 BEGIN 33 --根據表中字段組合實體類中的字段和屬性 34 DECLARE @nsql NVARCHAR(4000) , 35 @sql VARCHAR(8000); 36 SET @nsql = 'select @s=isnull(@s+char(9)+''private '',''using System;' 37 + CHAR(13) + 'using System.Collections.Generic;' 38 + CHAR(13) + 'using System.Text;' + CHAR(13) 39 + 'namespace ' + @namespace + CHAR(13) + '{' + CHAR(13) 40 + CHAR(9) + 'public class ' + @tablename + CHAR(13) 41 + '{''+char(13)+char(9)+''private '')+ 42 case when a.name in(''image'',''uniqueidentifier'',''ntext'',''varchar'',''ntext'',''nchar'',''nvarchar'',''text'',''char'') then ''string'' 43 when a.name in(''tinyint'',''smallint'',''int'',''bigint'') then ''int'' 44 when a.name in(''datetime'',''smalldatetime'') then ''DateTime'' 45 when a.name in(''float'',''decimal'',''numeric'',''money'',''real'',''smallmoney'') then ''decimal'' 46 when a.name =''bit'' then ''bool'' 47 else a.name end+'' ''+lower(''_''+b.name)+'';''+char(13)+char(9)+''public ''+ 48 case when a.name in(''image'',''uniqueidentifier'',''ntext'',''varchar'',''ntext'',''nchar'',''nvarchar'',''text'',''char'') then ''string'' 49 when a.name in(''tinyint'',''smallint'',''int'') then ''int'' 50 when a.name=''bigint'' then ''long'' 51 when a.name in(''datetime'',''smalldatetime'') then ''DateTime'' 52 when a.name in(''float'',''decimal'',''numeric'',''money'',''real'',''smallmoney'') then ''decimal'' 53 when a.name =''bit'' then ''bool'' 54 else a.name end 55 +'' ''+b.name+char(13)+char(9)+''{''+char(13)+char(9)+char(9)+''get{return ''+lower(''_''+b.name)+'';}''+ 56 char(13)+char(9)+char(9)+''set{''+lower(''_''+b.name)+''=value;}''+char(13)+char(9)+''}''+char(13) 57 from ' + @dbname + '..syscolumns b, 58 (select distinct name,xtype from ' + @dbname + '..systypes where status=0) a 59 where a.xtype=b.xtype and b.id=object_id(''' + @dbname + '..' + @tablename 60 + ''')'; 61 EXEC sp_executesql @nsql, N'@s varchar(8000) output', 62 @sql OUTPUT; 63 SET @sql = @sql + CHAR(9) + '}' + CHAR(13) + '}'; 64 --print @sql 65 DECLARE @err INT , 66 @fso INT , 67 @fleExists BIT , 68 @file VARCHAR(100); 69 SET @file = @path + '/' + @tablename + '.cs'; 70 EXEC @err= sp_OACreate 'Scripting.FileSystemObject', 71 @fso OUTPUT; 72 EXEC @err= sp_OAMethod @fso, 'FileExists', 73 @fleExists OUTPUT, @file; 74 EXEC @err = sp_OADestroy @fso; 75 76 IF @fleExists != 0 77 EXEC('exec xp_cmdshell ''del '+@file+''''); --存在則刪除 78 EXEC('exec xp_cmdshell ''echo '+@sql+' > '+@file+''''); --將文本寫進文件中 79 SET @sql = NULL; 80 FETCH wsp INTO @tablename; 81 END; 82 CLOSE wsp; 83 DEALLOCATE wsp; 84 PRINT '生成成功!'; 85 END; 86 ELSE 87 PRINT '數據庫不存在!';
調用存儲過程: EXEC [dbo].[p_db_wsp] '數據庫名字', '保存的路徑:D:\work\新建文件夾', '生成實體類名字';shell
上面的方法都是生成實體的,下面就是生成insert的方法數據庫
1 <#@ template language="C#" debug="True" hostspecific="True" #> 2 <#@ output extension=".cs" #> 3 <#@ assembly name="System.Data" #> 4 <#@ assembly name="System.xml" #> 5 <#@ import namespace="System.Collections.Generic" #> 6 <#@ import namespace="System.Data.SqlClient" #> 7 <#@ import namespace="System.Data" #> 8 using System.Collections.Generic; 9 using System.Linq; 10 using System.Text; 11 using System.Text.RegularExpressions; 12 using System.Windows.Forms; 13 using System.Data; 14 using CMS.Utilities; 15 using System.Data.OleDb; 16 using System.Configuration; 17 using System.Data.SqlClient; 18 using System; 19 namespace MyProject.Entitiese 20 { 21 <# 22 string connectionString = "server=192.168.2.230;database=tjprj;uid=erptest;pwd=test@123456"; 23 string selectQuery = "select * from Team_"; 24 string tableName="Team_"; 25 SqlConnection conn = new SqlConnection(connectionString); 26 conn.Open(); 27 System.Data.DataTable schema = null; 28 SqlCommand selectcommand = new SqlCommand(selectQuery, conn); 29 SqlDataAdapter sda = new SqlDataAdapter(selectcommand); 30 System.Data.DataSet dss = new System.Data.DataSet(); 31 sda.Fill(dss); 32 schema=dss.Tables[0]; 33 System.Data.DataTable dt = dss.Tables[0]; 34 System.Data.DataRow dr = dss.Tables[0].Rows[0]; 35 SqlCommand command = new SqlCommand(selectQuery,conn); 36 SqlDataAdapter ad = new SqlDataAdapter(command); 37 #> 38 public class <#= tableName#>Bizs 39 { 40 public class <#= tableName#>Models 41 { 42 <# foreach (DataColumn dc in dss.Tables[0].Columns) 43 { #> 44 private <#= dc.DataType.Name #> _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #>; 45 public <#= dc.DataType.Name #> <#= dc.ColumnName #> 46 { 47 get { return _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #>; } 48 set { _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #> = value; } 49 } 50 <# } #> 51 52 } 53 public bool Insert<#= tableName#>(<#= tableName#>Models model) 54 { 55 string strSql = @" 56 INSERT Team_( 57 <# foreach (DataColumn dc in dss.Tables[0].Columns) 58 { #><#= dc.ColumnName #>, 59 <# } #> 60 ) 61 VALUES ( 62 <# foreach (DataColumn dc in dss.Tables[0].Columns) 63 { #><#= dc.ColumnName #>, 64 <# } #> 65 ) 66 "; 67 SqlParameter[] parameters = new SqlParameter[] 68 { 69 <# foreach (DataColumn dc in dss.Tables[0].Columns) 70 { #> new SqlParameter("<#= dc.ColumnName #>,", SqlDbType.NVarChar, 255), 71 <# } #> 72 }; 73 <# for (int i = 0; i < dr.Table.Columns.Count; i++) 74 { #> parameters[<#=i#>].Value = model.<#=dr.Table.Columns[i] #>; 75 <# } #> 76 using (SqlConnection conn = new SqlConnection(SqlHelper.ConnectionString)) 77 { 78 conn.Open(); 79 using (SqlTransaction trans = conn.BeginTransaction()) 80 { 81 try 82 { 83 int i = SqlHelper.ExecuteNonQuery(trans, CommandType.Text, strSql, parameters); 84 if (i > 0) 85 { 86 trans.Commit(); 87 return i > 0; 88 } 89 else 90 { 91 trans.Rollback(); 92 return false; 93 } 94 } 95 catch (System.Exception e) 96 { 97 trans.Rollback(); 98 return false; 99 throw e; 100 } 101 } 102 } 103 } 104 105 106 } 107 108 }
生成代碼:app
1 using System.Collections.Generic; 2 using System.Linq; 3 using System.Text; 4 using System.Text.RegularExpressions; 5 using System.Windows.Forms; 6 using System.Data; 7 using CMS.Utilities; 8 using System.Data.OleDb; 9 using System.Configuration; 10 using System.Data.SqlClient; 11 using System; 12 namespace MyProject.Entitiese 13 { 14 15 public class Team_Bizs 16 { 17 public class Team_Models 18 { 19 20 private String _team_code; 21 public String Team_code 22 { 23 get { return _team_code; } 24 set { _team_code = value; } 25 } 26 27 private String _team_name; 28 public String Team_name 29 { 30 get { return _team_name; } 31 set { _team_name = value; } 32 } 33 34 private String _team_status; 35 public String Team_status 36 { 37 get { return _team_status; } 38 set { _team_status = value; } 39 } 40 41 private String _team_user; 42 public String Team_user 43 { 44 get { return _team_user; } 45 set { _team_user = value; } 46 } 47 48 private DateTime _team_date; 49 public DateTime Team_date 50 { 51 get { return _team_date; } 52 set { _team_date = value; } 53 } 54 55 56 } 57 public bool InsertTeam_(Team_Models model) 58 { 59 string strSql = @" 60 INSERT Team_( 61 Team_code, 62 Team_name, 63 Team_status, 64 Team_user, 65 Team_date, 66 67 ) 68 VALUES ( 69 Team_code, 70 Team_name, 71 Team_status, 72 Team_user, 73 Team_date, 74 75 ) 76 "; 77 SqlParameter[] parameters = new SqlParameter[] 78 { 79 new SqlParameter("Team_code,", SqlDbType.NVarChar, 255), 80 new SqlParameter("Team_name,", SqlDbType.NVarChar, 255), 81 new SqlParameter("Team_status,", SqlDbType.NVarChar, 255), 82 new SqlParameter("Team_user,", SqlDbType.NVarChar, 255), 83 new SqlParameter("Team_date,", SqlDbType.NVarChar, 255), 84 85 }; 86 parameters[0].Value = model.Team_code; 87 parameters[1].Value = model.Team_name; 88 parameters[2].Value = model.Team_status; 89 parameters[3].Value = model.Team_user; 90 parameters[4].Value = model.Team_date; 91 92 using (SqlConnection conn = new SqlConnection(SqlHelper.ConnectionString)) 93 { 94 conn.Open(); 95 using (SqlTransaction trans = conn.BeginTransaction()) 96 { 97 try 98 { 99 int i = SqlHelper.ExecuteNonQuery(trans, CommandType.Text, strSql, parameters); 100 if (i > 0) 101 { 102 trans.Commit(); 103 return i > 0; 104 } 105 else 106 { 107 trans.Rollback(); 108 return false; 109 } 110 } 111 catch (System.Exception e) 112 { 113 trans.Rollback(); 114 return false; 115 throw e; 116 } 117 } 118 } 119 } 120 121 122 } 123 124 }
方法與以前一篇文章和上面講到生成實體的方法差很少,還有update,select,delete 方法也是差很少的,我就再也不貼上代碼了。框架
github地址:https://github.com/Jimmey-Jiang/JWorkHelper稍後推送代碼上去。