好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

T4模版引擎之生成数据库实体类

在通过T4模版引擎之基础入门 对T4有了初步印象后,我们开始实战篇。T4模板引擎可以当做一个代码生成器,代码生成器的职责当然是用来生成代码(这不是废话吗)。而这其中我们使用的最普遍的是根据数据库生成实体类。 工欲善其事必先利其器,在这之前先来介绍一

  在通过T4模版引擎之基础入门 对T4有了初步印象后,我们开始实战篇。T4模板引擎可以当做一个代码生成器,代码生成器的职责当然是用来生成代码(这不是废话吗)。而这其中我们使用的最普遍的是根据数据库生成实体类。

  工欲善其事必先利其器,在这之前先来介绍一款T4编辑器T4 Editor,我们可以点击链接去下载然后安装,不过还是推荐大家直接在VS扩展管理器里直接安装来的方便 工具->扩展管理器->联机库 搜索 "T4 Editor",选择第一项 "tangible T4 Editor 2.0 plus modeling tools for VS2010" 进行安装即可,如下图所示:

安装上T4 Editor后,编辑T4模板是就有代码着色和智能提示了,下图为安装T4 Editor后的代码着色效果,怎么样是不是耳目一新,呵呵

接下来开始正式进入我们的主题,从数据库自动生成实体类

新建一个控制台项目,然后添加T4模板,这里我们起名字为Customers.tt

修改 输出文件扩展名为.cs

   #@ output   extension  =".cs"   #  >  

添加常用的程序集和命名空间引用

   #@ assembly   name  ="System.Core.dll"   #  > 
   #@ assembly   name  ="System.Data.dll"   #  > 
   #@ assembly   name  ="System.Data.DataSetExtensions.dll"   #  > 
   #@ assembly   name  ="System.Xml.dll"   #  > 
   #@ import   namespace  ="System"   #  > 
   #@ import   namespace  ="System.Xml"   #  > 
   #@ import   namespace  ="System.Linq"   #  > 
   #@ import   namespace  ="System.Data"   #  > 
   #@ import   namespace  ="System.Data.SqlClient"   #  > 
   #@ import   namespace  ="System.Collections.Generic"   #  > 
   #@ import   namespace  ="System.IO"   #  >  

添加数据库操作DbHelper引用

DbHelper.ttinclude

 public   class   DbHelper
    {
          #region  GetDbTables
        
         public   static  List  GetDbTables( string  connectionString,  string  database,  string  tables =  null  )
        {
            
              if  (! string  .IsNullOrEmpty(tables))
            {
                tables  =  string .Format( "   and obj.name in ('{0}')  " , tables.Replace( "  ,  " ,  "  ','  "  ));
            }
              #region  SQL
             string  sql =  string .Format( @"  SELECT
                                    obj.name tablename,
                                    schem.name schemname,
                                    idx.rows,
                                    CAST
                                    (
                                        CASE 
                                            WHEN (SELECT COUNT(1) FROM sys.indexes WHERE object_id= obj.OBJECT_ID AND is_primary_key=1) >=1 THEN 1
                                            ELSE 0
                                        END 
                                    AS BIT) HasPrimaryKey                                         
                                    from {0}.sys.objects obj 
                                    inner join {0}.dbo.sysindexes idx on obj.object_id=idx.id and idx.indid  "  , database, tables);
              #endregion  
            DataTable dt  =  GetDataTable(connectionString, sql);
              return  dt.Rows.Cast ().Select(row =>  new   DbTable
            {
                TableName  = row.Field string >( "  tablename  "  ),
                SchemaName  = row.Field string >( "  schemname  "  ),
                Rows  = row.Field int >( "  rows  "  ),
                HasPrimaryKey  = row.Field bool >( "  HasPrimaryKey  "  )
            }).ToList();
        }
          #endregion 

         #region  GetDbColumns
        
         public   static  List  GetDbColumns( string  connectionString,  string  database,  string  tableName,  string  schema =  "  dbo  "  )
        {
              #region  SQL
             string  sql =  string .Format( @"  
                                    WITH indexCTE AS
                                    (
                                        SELECT 
                                        ic.column_id,
                                        ic.index_column_id,
                                        ic.object_id    
                                        FROM {0}.sys.indexes idx
                                        INNER JOIN {0}.sys.index_columns ic ON idx.index_id = ic.index_id AND idx.object_id = ic.object_id
                                        WHERE  idx.object_id =OBJECT_ID(@tableName) AND idx.is_primary_key=1
                                    )
                                    select
                                    colm.column_id ColumnID,
                                    CAST(CASE WHEN indexCTE.column_id IS NULL THEN 0 ELSE 1 END AS BIT) IsPrimaryKey,
                                    colm.name ColumnName,
                                    systype.name ColumnType,
                                    colm.is_identity IsIdentity,
                                    colm.is_nullable IsNullable,
                                    cast(colm.max_length as int) ByteLength,
                                    (
                                        case 
                                            when systype.name='nvarchar' and colm.max_length>0 then colm.max_length/2 
                                            when systype.name='nchar' and colm.max_length>0 then colm.max_length/2
                                            when systype.name='ntext' and colm.max_length>0 then colm.max_length/2 
                                            else colm.max_length
                                        end
                                    ) CharLength,
                                    cast(colm.precision as int) Precision,
                                    cast(colm.scale as int) Scale,
                                    prop.value Remark
                                    from {0}.sys.columns colm
                                    inner join {0}.sys.types systype on colm.system_type_id=systype.system_type_id and colm.user_type_id=systype.user_type_id
                                    left join {0}.sys.extended_properties prop on colm.object_id=prop.major_id and colm.column_id=prop.minor_id
                                    LEFT JOIN indexCTE ON colm.column_id=indexCTE.column_id AND colm.object_id=indexCTE.object_id                                        
                                    where colm.object_id=OBJECT_ID(@tableName)
                                    order by colm.column_id  "  , database);
              #endregion  
            SqlParameter param  =  new  SqlParameter( "  @tableName  " , SqlDbType.NVarChar,  100 ) { Value =  string .Format( "  {0}.{1}.{2}  "  , database, schema, tableName) };
            DataTable dt  =  GetDataTable(connectionString, sql, param);
              return  dt.Rows.Cast ().Select(row =>  new   DbColumn()
            {
                ColumnID  = row.Field int >( "  ColumnID  "  ),
                IsPrimaryKey  = row.Field bool >( "  IsPrimaryKey  "  ),
                ColumnName  = row.Field string >( "  ColumnName  "  ),
                ColumnType  = row.Field string >( "  ColumnType  "  ),
                IsIdentity  = row.Field bool >( "  IsIdentity  "  ),
                IsNullable  = row.Field bool >( "  IsNullable  "  ),
                ByteLength  = row.Field int >( "  ByteLength  "  ),
                CharLength  = row.Field int >( "  CharLength  "  ),
                Scale  = row.Field int >( "  Scale  "  ),
                Remark  = row[ "  Remark  "  ].ToString()
            }).ToList();
        }

          #endregion      


         #region  GetDataTable
        
         public   static  DataTable GetDataTable( string  connectionString,  string  commandText,  params   SqlParameter[] parms)
        {
              using  (SqlConnection connection =  new   SqlConnection(connectionString))
            {
                SqlCommand command  =  connection.CreateCommand();
                command.CommandText  =  commandText;
                command.Parameters.AddRange(parms);
                SqlDataAdapter adapter  =  new   SqlDataAdapter(command);

                DataTable dt  =  new   DataTable();
                adapter.Fill(dt);

                  return   dt;
            }
        }

          #endregion  
    }

      #region  DbTable
     ///     
     ///   表结构
      ///     
     public   sealed   class   DbTable
    {
          ///     
         ///   表名称
          ///     
         public   string  TableName {  get ;  set  ; }
          ///     
         ///   表的架构
          ///     
         public   string  SchemaName {  get ;  set  ; }
          ///     
         ///   表的记录数
          ///     
         public   int  Rows {  get ;  set  ; }

          ///     
         ///   是否含有主键
          ///     
         public   bool  HasPrimaryKey {  get ;  set  ; }
    }
      #endregion 

     #region  DbColumn
     ///     
     ///   表字段结构
      ///     
     public   sealed   class   DbColumn
    {
          ///     
         ///   字段ID
          ///     
         public   int  ColumnID {  get ;  set  ; }

          ///     
         ///   是否主键
          ///     
         public   bool  IsPrimaryKey {  get ;  set  ; }

          ///     
         ///   字段名称
          ///     
         public   string  ColumnName {  get ;  set  ; }

          ///     
         ///   字段类型
          ///     
         public   string  ColumnType {  get ;  set  ; }

          ///     
         ///   数据库类型对应的C#类型
          ///     
         public   string   CSharpType
        {
              get  
            {
                  return   SqlServerDbTypeMap.MapCsharpType(ColumnType);
            }
        }

          ///     
         ///  
         ///     
         public   Type CommonType
        {
              get  
            {
                  return   SqlServerDbTypeMap.MapCommonType(ColumnType);
            }
        }

          ///     
         ///   字节长度
          ///     
         public   int  ByteLength {  get ;  set  ; }

          ///     
         ///   字符长度
          ///     
         public   int  CharLength {  get ;  set  ; }

          ///     
         ///   小数位
          ///     
         public   int  Scale {  get ;  set  ; }

          ///     
         ///   是否自增列
          ///     
         public   bool  IsIdentity {  get ;  set  ; }

          ///     
         ///   是否允许空
          ///     
         public   bool  IsNullable {  get ;  set  ; }

          ///     
         ///   描述
          ///     
         public   string  Remark {  get ;  set  ; }
    }
      #endregion 

     #region  SqlServerDbTypeMap

     public   class   SqlServerDbTypeMap
    {
          public   static   string  MapCsharpType( string   dbtype)
        {
              if  ( string .IsNullOrEmpty(dbtype))  return   dbtype;
            dbtype  =  dbtype.ToLower();
              string  csharpType =  "  object  "  ;
              switch   (dbtype)
            {
                  case   "  bigint  " : csharpType =  "  long  " ;  break  ;
                  case   "  binary  " : csharpType =  "  byte[]  " ;  break  ;
                  case   "  bit  " : csharpType =  "  bool  " ;  break  ;
                  case   "  char  " : csharpType =  "  string  " ;  break  ;
                  case   "  date  " : csharpType =  "  DateTime  " ;  break  ;
                  case   "  datetime  " : csharpType =  "  DateTime  " ;  break  ;
                  case   "  datetime2  " : csharpType =  "  DateTime  " ;  break  ;
                  case   "  datetimeoffset  " : csharpType =  "  DateTimeOffset  " ;  break  ;
                  case   "  decimal  " : csharpType =  "  decimal  " ;  break  ;
                  case   "  float  " : csharpType =  "  double  " ;  break  ;
                  case   "  image  " : csharpType =  "  byte[]  " ;  break  ;
                  case   "  int  " : csharpType =  "  int  " ;  break  ;
                  case   "  money  " : csharpType =  "  decimal  " ;  break  ;
                  case   "  nchar  " : csharpType =  "  string  " ;  break  ;
                  case   "  ntext  " : csharpType =  "  string  " ;  break  ;
                  case   "  numeric  " : csharpType =  "  decimal  " ;  break  ;
                  case   "  nvarchar  " : csharpType =  "  string  " ;  break  ;
                  case   "  real  " : csharpType =  "  Single  " ;  break  ;
                  case   "  smalldatetime  " : csharpType =  "  DateTime  " ;  break  ;
                  case   "  smallint  " : csharpType =  "  short  " ;  break  ;
                  case   "  smallmoney  " : csharpType =  "  decimal  " ;  break  ;
                  case   "  sql_variant  " : csharpType =  "  object  " ;  break  ;
                  case   "  sysname  " : csharpType =  "  object  " ;  break  ;
                  case   "  text  " : csharpType =  "  string  " ;  break  ;
                  case   "  time  " : csharpType =  "  TimeSpan  " ;  break  ;
                  case   "  timestamp  " : csharpType =  "  byte[]  " ;  break  ;
                  case   "  tinyint  " : csharpType =  "  byte  " ;  break  ;
                  case   "  uniqueidentifier  " : csharpType =  "  Guid  " ;  break  ;
                  case   "  varbinary  " : csharpType =  "  byte[]  " ;  break  ;
                  case   "  varchar  " : csharpType =  "  string  " ;  break  ;
                  case   "  xml  " : csharpType =  "  string  " ;  break  ;
                  default : csharpType =  "  object  " ;  break  ;
            }
              return   csharpType;
        }
           
          public   static  Type MapCommonType( string   dbtype)
        {
              if  ( string .IsNullOrEmpty(dbtype))  return   Type.Missing.GetType();
            dbtype  =  dbtype.ToLower();
            Type commonType  =  typeof ( object  );
              switch   (dbtype)
            {
                  case   "  bigint  " : commonType =  typeof ( long );  break  ;
                  case   "  binary  " : commonType =  typeof ( byte []);  break  ;
                  case   "  bit  " : commonType =  typeof ( bool );  break  ;
                  case   "  char  " : commonType =  typeof ( string );  break  ;
                  case   "  date  " : commonType =  typeof (DateTime);  break  ;
                  case   "  datetime  " : commonType =  typeof (DateTime);  break  ;
                  case   "  datetime2  " : commonType =  typeof (DateTime);  break  ;
                  case   "  datetimeoffset  " : commonType =  typeof (DateTimeOffset);  break  ;
                  case   "  decimal  " : commonType =  typeof ( decimal );  break  ;
                  case   "  float  " : commonType =  typeof ( double );  break  ;
                  case   "  image  " : commonType =  typeof ( byte []);  break  ;
                  case   "  int  " : commonType =  typeof ( int );  break  ;
                  case   "  money  " : commonType =  typeof ( decimal );  break  ;
                  case   "  nchar  " : commonType =  typeof ( string );  break  ;
                  case   "  ntext  " : commonType =  typeof ( string );  break  ;
                  case   "  numeric  " : commonType =  typeof ( decimal );  break  ;
                  case   "  nvarchar  " : commonType =  typeof ( string );  break  ;
                  case   "  real  " : commonType =  typeof (Single);  break  ;
                  case   "  smalldatetime  " : commonType =  typeof (DateTime);  break  ;
                  case   "  smallint  " : commonType =  typeof ( short );  break  ;
                  case   "  smallmoney  " : commonType =  typeof ( decimal );  break  ;
                  case   "  sql_variant  " : commonType =  typeof ( object );  break  ;
                  case   "  sysname  " : commonType =  typeof ( object );  break  ;
                  case   "  text  " : commonType =  typeof ( string );  break  ;
                  case   "  time  " : commonType =  typeof (TimeSpan);  break  ;
                  case   "  timestamp  " : commonType =  typeof ( byte []);  break  ;
                  case   "  tinyint  " : commonType =  typeof ( byte );  break  ;
                  case   "  uniqueidentifier  " : commonType =  typeof (Guid);  break  ;
                  case   "  varbinary  " : commonType =  typeof ( byte []);  break  ;
                  case   "  varchar  " : commonType =  typeof ( string );  break  ;
                  case   "  xml  " : commonType =  typeof ( string );  break  ;
                  default : commonType =  typeof ( object );  break  ;
            }
              return   commonType;
        }
    }
      #endregion  
    

# > 

   #@ include   file  ="$(ProjectDir)DbHelper.ttinclude"    #  >  

DbHelper相对比较复杂,把一些常用操作进行了简单封装,因此放到一个单独的文件里面进行引用,可以方便的进行复用,这里DbHelper的后缀名使用ttinclude,这里的后缀名可以随便起,按照微软的建议: 用于include的文件尽量不要使用.tt做后缀名

在页面底部定义一些常用变量,以方便操作

 public   class   config
    {
          public   static   readonly   string  ConnectionString= "  Data Source=(local);Integrated Security=true;Initial Catalog=Northwind;  "  ;
          public   static   readonly   string  DbDatabase= "  Northwind  "  ;
          public   static   readonly   string  TableName= "  Customers  "  ;
    }
# > 

这里我们把数据库连接串和数据库、表名字定义一下,方便修改和使用

最后来编写用于实体类生成的代码

 //  ------------------------------------------------------------------------------
  //   
  //       此代码由T4模板自动生成
  //         生成时间   by 懒惰的肥兔
  //       对此文件的更改可能会导致不正确的行为,并且如果
  //       重新生成代码,这些更改将会丢失。
  //    
  //  ------------------------------------------------------------------------------ 

 using   System;
  namespace   T4ConsoleApplication.Entities
{    

      public   class    
    {
          foreach (DbColumn column  in  DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, config.TableName)){#>

         ///     
         ///     
         ///             
         public    if (column.CommonType.IsValueType && column.IsNullable){#>?    {  get ;  set  ; }
            
      
    }
}  

全部完成后我们的Customers.tt文件就编写好了

Customers.tt

 "  false  "  hostspecific= "  false  "  language= "  C#  "  #>
 "  .cs  "  #>
 "  System.Core.dll  "  #>
 "  System.Data.dll  "  #>
 "  System.Data.DataSetExtensions.dll  "  #>
 "  System.Xml.dll  "  #>
 namespace = "  System  "  #>
 namespace = "  System.Xml  "  #>
 namespace = "  System.Linq  "  #>
 namespace = "  System.Data  "  #>
 namespace = "  System.Data.SqlClient  "  #>
 namespace = "  System.Collections.Generic  "  #>
 namespace = "  System.IO  "  #>
 "  $(ProjectDir)DbHelper.ttinclude  "   #>
 //  ------------------------------------------------------------------------------
  //   
  //       此代码由T4模板自动生成
  //         生成时间   by 懒惰的肥兔
  //       对此文件的更改可能会导致不正确的行为,并且如果
  //       重新生成代码,这些更改将会丢失。
  //    
  //  ------------------------------------------------------------------------------ 

 using   System;
  namespace   T4ConsoleApplication.Entities
{    

      public   class    
    {
          foreach (DbColumn column  in  DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, config.TableName)){#>

         ///     
         ///     
         ///             
         public    if (column.CommonType.IsValueType && column.IsNullable){#>?    {  get ;  set  ; }
            
      
    }
}

  public   class   config
    {
          public   static   readonly   string  ConnectionString= "  Data Source=(local);Integrated Security=true;Initial Catalog=Northwind;  "  ;
          public   static   readonly   string  DbDatabase= "  Northwind  "  ;
          public   static   readonly   string  TableName= "  Customers  "  ;
    }
# > 

进行保存后会自动生成Customers.cs文件

Customers.cs

 //  ------------------------------------------------------------------------------
  //   
  //       此代码由T4模板自动生成
  //         生成时间 2012-07-18 17:51:26 by 懒惰的肥兔
  //       对此文件的更改可能会导致不正确的行为,并且如果
  //       重新生成代码,这些更改将会丢失。
  //    
  //  ------------------------------------------------------------------------------ 

 using   System;
  namespace   T4ConsoleApplication.Entities
{    

      public   class   Customers
    {
        
          ///     
         ///  
         ///             
         public   string  CustomerID {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  CompanyName {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  ContactName {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  ContactTitle {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  Address {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  City {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  Region {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  PostalCode {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  Country {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  Phone {  get ;  set  ; }
        
          ///     
         ///  
         ///             
         public   string  Fax {  get ;  set  ; }
         
      
    }
}  

  至此完整演示了怎样一步步根据数据库生成实体类的操作,是不是很简单,如对语法和操作不理解的地方可以参考T4模版引擎之基础入门,稍微用心研究下,轻松打造属于自己的代码生成器。

通过单个T4模板生成多个文件 ,以及 自动生成整个数据库的所有实体类 ,敬请期待

  下班了,拍拍屁股走人。。。

源码:T4ConsoleApplication.rar

查看更多关于T4模版引擎之生成数据库实体类的详细内容...

  阅读:34次