懶人小工具:T4自動(dòng)生成Model,Insert,Select,Delete以及導(dǎo)出Excel的方法

之前寫了篇文章时迫,懶人小工具:自動(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ò)展的頁面

2.png

3.png

4.png

5.png

6.png
1.png

現(xiàn)在添加了安裝包,直接點(diǎn)擊下一步下一步就可以了凤瘦,在桌面生成工具宿礁,點(diǎn)擊工具可以用了

安裝包.png

一、下面我就用最簡(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í)體類捍靠。

1.png

二沐旨、 根據(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鬼贱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子香璃,更是在濱河造成了極大的恐慌这难,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葡秒,死亡現(xiàn)場(chǎng)離奇詭異姻乓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)眯牧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門蹋岩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人学少,你說我怎么就攤上這事剪个。” “怎么了版确?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵扣囊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我绒疗,道長(zhǎng)侵歇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任吓蘑,我火速辦了婚禮盒至,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己枷遂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布棋嘲。 她就那樣靜靜地躺著酒唉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沸移。 梳的紋絲不亂的頭發(fā)上痪伦,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音雹锣,去河邊找鬼网沾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蕊爵,可吹牛的內(nèi)容都是我干的辉哥。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼攒射,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼醋旦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起会放,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤饲齐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后咧最,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捂人,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年矢沿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滥搭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咨察,死狀恐怖论熙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摄狱,我是刑警寧澤脓诡,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站媒役,受9級(jí)特大地震影響祝谚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酣衷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一交惯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦席爽、人聲如沸意荤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玖像。三九已至,卻和暖如春齐饮,著一層夾襖步出監(jiān)牢的瞬間捐寥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國打工祖驱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留握恳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓捺僻,卻偏偏與公主長(zhǎng)得像乡洼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陵像,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361