懒人小工具:T4自动生成Model,Insert,Select,Delete以及导出Excel的方法

之前写了篇文章,懒人小工具:自动生成Model,Insert,Select,Delete以及导出Excel的方法,但是有人觉得这种方法很麻烦。其实我感觉确实是有点麻烦,麻烦在于字符串的拼接。
这种时候我想到了T4模板,用过EF的 DatabaseFirst自动生成实体的同学就明白,dbfirst 自带T4模板,之前我们在学习spring.net框架的时候,也有用过T4模板根据数映射到实体类自动创建仓储。T4模板其实还有很多应用的场景。
T4模板确实挺方便的,但是其实其中用过的原理和我之前做winform小工具差不多。都是根据数据字段和类型的映射生成实体。另外就是ado.net基础知识。
但是这种方法你得了解T4模板的基础语法。各有利弊,但是其实语法也不是很难.
先预览下扩展的页面

2.png

3.png

4.png

5.png

6.png
1.png

现在添加了安装包,直接点击下一步下一步就可以了,在桌面生成工具,点击工具可以用了

安装包.png

一、下面我就用最简单的方式用T4模板创建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; }
             }                                                
              <# }  #>     
     
           }     
           

   }
          
}

这种方式是挺简单的。<#@ import namespace="System.Data" #>这段代码是引用命名空间,在你后台代码中用,也就是包括下面ado.net中需要引用的命名空间,基本都写在这里。用 <#...dosomething...#>这段就是不用展示出来的代码,其他的代码就是在你用T4模板生成的时候要用的代码。是不是很简单。上面的代码无需详细解释了吧,运用ado.net链接数据库,获取表字段和类型。Ctrl+S就自动生成了实体类。

1.png

二、 根据模板生成的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; }
            }
        }

    }

}

上面这种是单独某张表的Model生成,下面这段代码是数据库所有表生成实体。大同小异,注意细节。

三、数据库所有表所有实体

<#@ 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");是获取数据库所有表名,然后遍历所有表名遍历表字段和类型,根据这些表生成实体。
另外还有一种方法是用数据存储过程自动生成实体。这种方法就需要SQL的基础知识了。

四、存储过程生成实体

SET ANSI_NULLS ON;  
SET QUOTED_IDENTIFIER ON;  
GO  
   
CREATE PROC [dbo].[p_db_wsp]
    @dbname VARCHAR(50) ,   --数据库名  
    @path VARCHAR(100) ,    --实体类所在目录名,如D:/My/Models  
    @namespace VARCHAR(50) --实体类命名空间,默认值为Models  
AS --判断数据库是否存在  
    IF ( DB_ID(@dbname) IS NOT NULL )
        BEGIN  
            IF ( ISNULL(@namespace, '') = '' )
                SET @namespace = 'Models';  
-- 允许配置高级选项  
            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;--使用游标循环遍历数据库中每个表  
            WHILE ( @@fetch_status = 0 )
                BEGIN  
--根据表中字段组合实体类中的字段和属性  
                    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+''''); --将文本写进文件中  
                    SET @sql = NULL;  
                    FETCH wsp INTO @tablename;  
                END;  
            CLOSE wsp;  
            DEALLOCATE wsp;  
            PRINT '生成成功!';  
        END;  
    ELSE
        PRINT '数据库不存在!';  

调用存储过程: EXEC [dbo].[p_db_wsp] '数据库名字', '保存的路径:D:\work\新建文件夹', '生成实体类名字';
另外:github地址https://github.com/Jimmey-Jiang/JWorkHelper

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342