之前寫了篇文章时迫,懶人小工具:自動(dòng)生成Model,Insert,Select,Delete以及導(dǎo)出Excel的方法,但是有人覺得這種方法很麻煩。其實(shí)我感覺確實(shí)是有點(diǎn)麻煩谓晌,麻煩在于字符串的拼接掠拳。
這種時(shí)候我想到了T4模板,用過EF的 DatabaseFirst自動(dòng)生成實(shí)體的同學(xué)就明白纸肉,dbfirst 自帶T4模板溺欧,之前我們?cè)趯W(xué)習(xí)spring.net框架的時(shí)候,也有用過T4模板根據(jù)數(shù)映射到實(shí)體類自動(dòng)創(chuàng)建倉儲(chǔ)柏肪。T4模板其實(shí)還有很多應(yīng)用的場(chǎng)景姐刁。
T4模板確實(shí)挺方便的,但是其實(shí)其中用過的原理和我之前做winform小工具差不多预吆。都是根據(jù)數(shù)據(jù)字段和類型的映射生成實(shí)體龙填。另外就是ado.net基礎(chǔ)知識(shí)。
但是這種方法你得了解T4模板的基礎(chǔ)語法拐叉。各有利弊岩遗,但是其實(shí)語法也不是很難.
先預(yù)覽下擴(kuò)展的頁面
現(xiàn)在添加了安裝包,直接點(diǎn)擊下一步下一步就可以了凤瘦,在桌面生成工具宿礁,點(diǎn)擊工具可以用了
一、下面我就用最簡(jiǎn)單的方式用T4模板創(chuàng)建Model.
<#@ template language="C#" debug="True" hostspecific="True" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Data" #>
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Data;
using CMS.Utilities;
using System.Data.OleDb;
using System.Configuration;
using System.Data.SqlClient;
using System;
namespace MyProject.Entities
{
<#
string connectionString = "server=192.168.2.230;database=databasename;uid=uid;pwd=123456";
string selectQuery = "select * from Team_";
string tableName="Team_";
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
System.Data.DataTable schema = null;
SqlCommand selectcommand = new SqlCommand(selectQuery, conn);
SqlDataAdapter sda = new SqlDataAdapter(selectcommand);
System.Data.DataSet dss = new System.Data.DataSet();
sda.Fill(dss);
schema=dss.Tables[0];
System.Data.DataTable dt = dss.Tables[0];
System.Data.DataRow dr = dss.Tables[0].Rows[0];
SqlCommand command = new SqlCommand(selectQuery,conn);
SqlDataAdapter ad = new SqlDataAdapter(command);
#>
public class <#= tableName#>Biz
{
public class <#= tableName#>Model
{
<# foreach (DataColumn dc in dss.Tables[0].Columns)
{ #>
private <#= dc.DataType.Name #> _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #>;
public <#= dc.DataType.Name #> <#= dc.ColumnName #>
{
get { return _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #>; }
set { _<#= dc.ColumnName.Replace(dc.ColumnName[0].ToString(), dc.ColumnName[0].ToString().ToLower()) #> = value; }
}
<# } #>
}
}
}
這種方式是挺簡(jiǎn)單的蔬芥。<#@ import namespace="System.Data" #>這段代碼是引用命名空間梆靖,在你后臺(tái)代碼中用,也就是包括下面ado.net中需要引用的命名空間笔诵,基本都寫在這里返吻。用 <#...dosomething...#>這段就是不用展示出來的代碼,其他的代碼就是在你用T4模板生成的時(shí)候要用的代碼乎婿。是不是很簡(jiǎn)單测僵。上面的代碼無需詳細(xì)解釋了吧,運(yùn)用ado.net鏈接數(shù)據(jù)庫,獲取表字段和類型。Ctrl+S就自動(dòng)生成了實(shí)體類捍靠。
二沐旨、 根據(jù)模板生成的Model
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Data;
using CMS.Utilities;
using System.Data.OleDb;
using System.Configuration;
using System.Data.SqlClient;
using System;
namespace MyProject.Entities
{
public class Team_Biz
{
public class Team_Model
{
private String _team_code;
public String Team_code
{
get { return _team_code; }
set { _team_code = value; }
}
private String _team_name;
public String Team_name
{
get { return _team_name; }
set { _team_name = value; }
}
private String _team_status;
public String Team_status
{
get { return _team_status; }
set { _team_status = value; }
}
private String _team_user;
public String Team_user
{
get { return _team_user; }
set { _team_user = value; }
}
private DateTime _team_date;
public DateTime Team_date
{
get { return _team_date; }
set { _team_date = value; }
}
}
}
}
上面這種是單獨(dú)某張表的Model生成,下面這段代碼是數(shù)據(jù)庫所有表生成實(shí)體榨婆。大同小異磁携,注意細(xì)節(jié)。
三良风、數(shù)據(jù)庫所有表所有實(shí)體
<#@ template language="C#" debug="True" hostspecific="True" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Data" #>
<#@ output extension=".cs" #>
using System;
namespace Test.T4
{
<#
string connectionString="data source=(local);initial catalog=musicstore;user id=sa;password=123456;";
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
DataTable schema = conn.GetSchema("TABLES");
string strSql = "select * from @tableName";
SqlCommand command = new SqlCommand(strSql,conn);
SqlDataAdapter ad = new SqlDataAdapter(command);
DataSet ds = new DataSet();
foreach(DataRow row in schema.Rows)
{ #>
public class <#= row["TABLE_NAME"].ToString().Trim() #>
{ <#
ds.Tables.Clear();
command.CommandText = strSql.Replace("@tableName",row["TABLE_NAME"].ToString());
ad.FillSchema(ds, SchemaType.Mapped, row["TABLE_NAME"].ToString());
foreach (DataColumn dc in ds.Tables[0].Columns)
{ #>
public <#= dc.DataType.Name #> <#= dc.ColumnName #> { get; set; }
<# } #>
}
<#
} #>
<# conn.Close(); #>
}
DataTable schema = conn.GetSchema("TABLES");是獲取數(shù)據(jù)庫所有表名谊迄,然后遍歷所有表名遍歷表字段和類型,根據(jù)這些表生成實(shí)體拖吼。
另外還有一種方法是用數(shù)據(jù)存儲(chǔ)過程自動(dòng)生成實(shí)體鳞上。這種方法就需要SQL的基礎(chǔ)知識(shí)了。
四吊档、存儲(chǔ)過程生成實(shí)體
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
GO
CREATE PROC [dbo].[p_db_wsp]
@dbname VARCHAR(50) , --數(shù)據(jù)庫名
@path VARCHAR(100) , --實(shí)體類所在目錄名篙议,如D:/My/Models
@namespace VARCHAR(50) --實(shí)體類命名空間,默認(rèn)值為Models
AS --判斷數(shù)據(jù)庫是否存在
IF ( DB_ID(@dbname) IS NOT NULL )
BEGIN
IF ( ISNULL(@namespace, '') = '' )
SET @namespace = 'Models';
-- 允許配置高級(jí)選項(xiàng)
EXEC sp_configure 'show advanced options', 1;
-- 重新配置
RECONFIGURE;
-- 啟用Ole Automation Procedures
EXEC sp_configure 'Ole Automation Procedures', 1;
-- 啟用xp_cmdshell,可以向磁盤中寫入文件
EXEC sp_configure 'xp_cmdshell', 1;
-- 重新配置
RECONFIGURE;
DECLARE @dbsql VARCHAR(1000) ,
@tablename VARCHAR(100);
SET @dbsql = 'declare wsp cursor for select name from ' + @dbname
+ '..sysobjects where xtype=''u'' and name <>''sysdiagrams''';
EXEC(@dbsql);
OPEN wsp;
FETCH wsp INTO @tablename;--使用游標(biāo)循環(huán)遍歷數(shù)據(jù)庫中每個(gè)表
WHILE ( @@fetch_status = 0 )
BEGIN
--根據(jù)表中字段組合實(shí)體類中的字段和屬性
DECLARE @nsql NVARCHAR(4000) ,
@sql VARCHAR(8000);
SET @nsql = 'select @s=isnull(@s+char(9)+''private '',''using System;'
+ CHAR(13) + 'using System.Collections.Generic;'
+ CHAR(13) + 'using System.Text;' + CHAR(13)
+ 'namespace ' + @namespace + CHAR(13) + '{' + CHAR(13)
+ CHAR(9) + 'public class ' + @tablename + CHAR(13)
+ '{''+char(13)+char(9)+''private '')+
case when a.name in(''image'',''uniqueidentifier'',''ntext'',''varchar'',''ntext'',''nchar'',''nvarchar'',''text'',''char'') then ''string''
when a.name in(''tinyint'',''smallint'',''int'',''bigint'') then ''int''
when a.name in(''datetime'',''smalldatetime'') then ''DateTime''
when a.name in(''float'',''decimal'',''numeric'',''money'',''real'',''smallmoney'') then ''decimal''
when a.name =''bit'' then ''bool''
else a.name end+'' ''+lower(''_''+b.name)+'';''+char(13)+char(9)+''public ''+
case when a.name in(''image'',''uniqueidentifier'',''ntext'',''varchar'',''ntext'',''nchar'',''nvarchar'',''text'',''char'') then ''string''
when a.name in(''tinyint'',''smallint'',''int'') then ''int''
when a.name=''bigint'' then ''long''
when a.name in(''datetime'',''smalldatetime'') then ''DateTime''
when a.name in(''float'',''decimal'',''numeric'',''money'',''real'',''smallmoney'') then ''decimal''
when a.name =''bit'' then ''bool''
else a.name end
+'' ''+b.name+char(13)+char(9)+''{''+char(13)+char(9)+char(9)+''get{return ''+lower(''_''+b.name)+'';}''+
char(13)+char(9)+char(9)+''set{''+lower(''_''+b.name)+''=value;}''+char(13)+char(9)+''}''+char(13)
from ' + @dbname + '..syscolumns b,
(select distinct name,xtype from ' + @dbname + '..systypes where status=0) a
where a.xtype=b.xtype and b.id=object_id(''' + @dbname + '..' + @tablename
+ ''')';
EXEC sp_executesql @nsql, N'@s varchar(8000) output',
@sql OUTPUT;
SET @sql = @sql + CHAR(9) + '}' + CHAR(13) + '}';
--print @sql
DECLARE @err INT ,
@fso INT ,
@fleExists BIT ,
@file VARCHAR(100);
SET @file = @path + '/' + @tablename + '.cs';
EXEC @err= sp_OACreate 'Scripting.FileSystemObject',
@fso OUTPUT;
EXEC @err= sp_OAMethod @fso, 'FileExists',
@fleExists OUTPUT, @file;
EXEC @err = sp_OADestroy @fso;
IF @fleExists != 0
EXEC('exec xp_cmdshell ''del '+@file+''''); --存在則刪除
EXEC('exec xp_cmdshell ''echo '+@sql+' > '+@file+''''); --將文本寫進(jìn)文件中
SET @sql = NULL;
FETCH wsp INTO @tablename;
END;
CLOSE wsp;
DEALLOCATE wsp;
PRINT '生成成功!';
END;
ELSE
PRINT '數(shù)據(jù)庫不存在怠硼!';
調(diào)用存儲(chǔ)過程: EXEC [dbo].[p_db_wsp] '數(shù)據(jù)庫名字', '保存的路徑:D:\work\新建文件夾', '生成實(shí)體類名字';
另外:github地址:https://github.com/Jimmey-Jiang/JWorkHelper