本文转自:http://www.cnblogs.com/lzrabbit/archive/2012/07/18/2597953.html

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

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

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

 

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

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

  2. 修改输出文件扩展名为.cs
    <#@ output extension=".cs" #>
  3. 添加常用的程序集和命名空间引用
    <#@ 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" #>
  4. 添加数据库操作DbHelper引用
    <#+
    public class DbHelper
    {
    #region GetDbTables public static List<DbTable> 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<=1
    INNER JOIN {0}.sys.schemas schem ON obj.schema_id=schem.schema_id
    where type='U' {1}
    order by obj.name", database, tables);
    #endregion
    DataTable dt = GetDataTable(connectionString, sql);
    return dt.Rows.Cast<DataRow>().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<DbColumn> 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<DataRow>().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
    /// <summary>
    /// 表结构
    /// </summary>
    public sealed class DbTable
    {
    /// <summary>
    /// 表名称
    /// </summary>
    public string TableName { get; set; }
    /// <summary>
    /// 表的架构
    /// </summary>
    public string SchemaName { get; set; }
    /// <summary>
    /// 表的记录数
    /// </summary>
    public int Rows { get; set; } /// <summary>
    /// 是否含有主键
    /// </summary>
    public bool HasPrimaryKey { get; set; }
    }
    #endregion #region DbColumn
    /// <summary>
    /// 表字段结构
    /// </summary>
    public sealed class DbColumn
    {
    /// <summary>
    /// 字段ID
    /// </summary>
    public int ColumnID { get; set; } /// <summary>
    /// 是否主键
    /// </summary>
    public bool IsPrimaryKey { get; set; } /// <summary>
    /// 字段名称
    /// </summary>
    public string ColumnName { get; set; } /// <summary>
    /// 字段类型
    /// </summary>
    public string ColumnType { get; set; } /// <summary>
    /// 数据库类型对应的C#类型
    /// </summary>
    public string CSharpType
    {
    get
    {
    return SqlServerDbTypeMap.MapCsharpType(ColumnType);
    }
    } /// <summary>
    ///
    /// </summary>
    public Type CommonType
    {
    get
    {
    return SqlServerDbTypeMap.MapCommonType(ColumnType);
    }
    } /// <summary>
    /// 字节长度
    /// </summary>
    public int ByteLength { get; set; } /// <summary>
    /// 字符长度
    /// </summary>
    public int CharLength { get; set; } /// <summary>
    /// 小数位
    /// </summary>
    public int Scale { get; set; } /// <summary>
    /// 是否自增列
    /// </summary>
    public bool IsIdentity { get; set; } /// <summary>
    /// 是否允许空
    /// </summary>
    public bool IsNullable { get; set; } /// <summary>
    /// 描述
    /// </summary>
    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做后缀名

  5. 在页面底部定义一些常用变量,以方便操作
    <#+
    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";
    }
    #>

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

  6. 最后来编写用于实体类生成的代码
    //------------------------------------------------------------------------------
    // <auto-generated>
    // 此代码由T4模板自动生成
    // 生成时间 <#=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")#> by 懒惰的肥兔
    // 对此文件的更改可能会导致不正确的行为,并且如果
    // 重新生成代码,这些更改将会丢失。
    // </auto-generated>
    //------------------------------------------------------------------------------ using System;
    namespace T4ConsoleApplication.Entities
    { public class <#=config.TableName#>
    {
    <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, config.TableName)){#> /// <summary>
    /// <#=column.Remark#>
    /// </summary>
    public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; }
    <#}#> }
    }
  7. 全部完成后我们的Customers.tt文件就编写好了
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ 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" #>
    <#@ include file="$(ProjectDir)DbHelper.ttinclude" #>
    //------------------------------------------------------------------------------
    // <auto-generated>
    // 此代码由T4模板自动生成
    // 生成时间 <#=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")#> by 懒惰的肥兔
    // 对此文件的更改可能会导致不正确的行为,并且如果
    // 重新生成代码,这些更改将会丢失。
    // </auto-generated>
    //------------------------------------------------------------------------------ using System;
    namespace T4ConsoleApplication.Entities
    { public class <#=config.TableName#>
    {
    <# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, config.TableName)){#> /// <summary>
    /// <#=column.Remark#>
    /// </summary>
    public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { 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文件

    //------------------------------------------------------------------------------
    // <auto-generated>
    // 此代码由T4模板自动生成
    // 生成时间 2012-07-18 17:51:26 by 懒惰的肥兔
    // 对此文件的更改可能会导致不正确的行为,并且如果
    // 重新生成代码,这些更改将会丢失。
    // </auto-generated>
    //------------------------------------------------------------------------------ using System;
    namespace T4ConsoleApplication.Entities
    { public class Customers
    { /// <summary>
    ///
    /// </summary>
    public string CustomerID { get; set; } /// <summary>
    ///
    /// </summary>
    public string CompanyName { get; set; } /// <summary>
    ///
    /// </summary>
    public string ContactName { get; set; } /// <summary>
    ///
    /// </summary>
    public string ContactTitle { get; set; } /// <summary>
    ///
    /// </summary>
    public string Address { get; set; } /// <summary>
    ///
    /// </summary>
    public string City { get; set; } /// <summary>
    ///
    /// </summary>
    public string Region { get; set; } /// <summary>
    ///
    /// </summary>
    public string PostalCode { get; set; } /// <summary>
    ///
    /// </summary>
    public string Country { get; set; } /// <summary>
    ///
    /// </summary>
    public string Phone { get; set; } /// <summary>
    ///
    /// </summary>
    public string Fax { get; set; } }
    }

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

  本文简单介绍了基于单个模板生成数据库实体类的示例,离具体实用还有一定的距离,毕竟总不能为每个数据表建一个模板吧,下一篇将揭晓如何通过单个T4模板生成多个文件,以及自动生成整个数据库的所有实体类,敬请期待

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

源码:T4ConsoleApplication.rar

注:此文章属懒惰的肥兔原创,版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接:http://www.cnblogs.com/lzrabbit/archive/2012/07/18/2597953.html

若您觉得这篇文章还不错请点击下右下角的推荐,有了您的支持才能激发作者更大的写作热情,非常感谢。

如有问题,可以通过lzrabbit@126.com联系我。

[转]T4模版引擎之生成数据库实体类的更多相关文章

  1. T4教程2 T4模版引擎之生成数据库实体类

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

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

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

  3. 【EF框架】EF DBFirst 快速生成数据库实体类 Database1.tt

    现有如下需求,数据库表快速映射到数据库实体类 VS给出的两个选择都有问题,并不能实现,都是坑啊 EF .x DbContext 生成器 EF .x DbContext 生成器 测试结果如下 生成文件 ...

  4. T4 生成数据库实体类

    来源不详,整理如下: <#@ template language="C#" debug="True" hostspecific="True&qu ...

  5. IntelliJ IDEA 学习(四)Idea逆向生成数据库实体类

    第一步配置 数据库 第二步  配置hibernate,如果没有cfg.xml文件,点击ok后会自动生成 第三步 选择hibernate配置文件生成实体 第四步 设置完点击,选中要生成的实体的表 注意: ...

  6. C# T4 模板 数据库实体类生成模板(带注释,娱乐用)

     说明:..,有些工具生成实体类没注释,不能和SqlServer的MS_Description属性一起使用,然后照着网上的资源,随便写了个生成模板,自娱自乐向,其实卵用都没有参考教程    1.htt ...

  7. 使用T4模板生成MySql数据库实体类

    注:本文系作者原创,但可随意转载. 现在呆的公司使用的数据库几乎都是MySQL.编程方式DatabaseFirst.即先写数据库设计,表设计按照规范好的文档写进EXCEL里,然后用公司的宏,生成建表脚 ...

  8. T4教程1 T4模版引擎之基础入门

    T4模版引擎之基础入门   额,T4好陌生的名字,和NuGet一样很悲催,不为世人所熟知,却又在背后默默无闻的奉献着,直到现在我们项目组的人除了我之外,其它人还是对其豪无兴趣,基本上是连看一眼都懒得看 ...

  9. 黄聪:VS2010开发T4模版引擎之基础入门

    原文:http://www.cnblogs.com/lzrabbit/archive/2012/07/15/2591085.html 额,T4好陌生的名字,和NuGet一样很悲催,不为世人所熟知,却又 ...

随机推荐

  1. 【转】iOS 硬件授权检测:定位服务、通讯录、日历、提醒事项、照片、蓝牙共享、麦克风、相机等

    iOS系统版本的不断升级的前提,伴随着用户使用设备的安全性提升,iOS系统对于App需要使用的硬件限制也越来越严格,App处理稍有不妥,轻则造成功能不可用用户还不知道,重则会造成App Crash. ...

  2. PLSQL Developer 常用设置及快捷键

    1.登录后自动选中My Objects(已验证可用) 默认情况下,PLSQL Developer登录后,Brower里会选择all Objects,如果你登录的用户是DBA, 要展开tables目录, ...

  3. Spring MVC ControllerClassNameHandlerMapping example

    handler mapping是把url跟控制器关联起来. In Spring MVC, ControllerClassNameHandlerMapping use convention to map ...

  4. [iOS 多线程 & 网络 - 2.8] - 检测网络状态

    A.说明 在网络应用中,需要对用户设备的网络状态进行实时监控,有两个目的:(1)让用户了解自己的网络状态,防止一些误会(比如怪应用无能)(2)根据用户的网络状态进行智能处理,节省用户流量,提高用户体验 ...

  5. HDU 5768 Lucky7 (中国剩余定理+容斥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5768 给你n个同余方程组,然后给你l,r,问你l,r中有多少数%7=0且%ai != bi. 比较明显 ...

  6. jquery validation ajax 验证

    <link href="${base}/res/basic/css/jquery/validationEngine/validationEngine.jquery.css" ...

  7. MySQL timestamp用法

    与timestamp类型相关的类型包括:date类型与datetime类型.date类型只包含日期部分,不包含时间部分,它的格式为'YYYY-MM-DD',支持的范围为'1000-01-01' to ...

  8. ldap

    年1月份最新的包.       安装前的准备工作 # mkdir ?p /data/packages//习惯性的把一些包放在一个位置 # yum install openldap-devel zlib ...

  9. cdoj 1250 喵哈哈的矩阵 数学题

    喵哈哈的矩阵 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1250 Desc ...

  10. Educational Codeforces Round 1 B. Queries on a String 暴力

    B. Queries on a String Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/59 ...