如何使用CodeSmith生成Model
2008-01-29 16:39
483 查看
在项目中,我们在持久化的时候,通常会使用Model层来封装数据——以便于传输,甚至页面的数据绑定时,也通过了Model:通过反射和遍历页面控件的方式。而当我们表格多的时候,写Model是一件很烦的事情——重复无意义的工作,而且还容易出错。看看你的Model吧,绝大部分都是成员变量的声明和属性的定义。
为什么我们不将这件工作交给一个工具来完成呢?
CodeSmith是个很强大的Code生成工具,可以操作数据库、Collection(.net)集合类型等等,可生成c#、js、vb、HashTable、List、Query、Xml,自成一套语法规则。(Eclipse将这个生成工作集成到它的IDE里面去了,虽然没这么强大,当然,你写好模板还是可以生成java代码的)。它的工作原理很简单:读模板文件、用数据覆盖标记、写文件等等,只不过,它将添加了链接了数据库等功能,直接图形化操作,可设置断点调试,解释执行,方便Debug。
好吧,闲话不多少,我们开始本文的主体部分。
首先,你需要下载CodeSmith,并安装(网上有注册机,本文基于V3.2版本)。打开CodeSmith Studio,新建一个c#模板(菜单栏File->New->c# Template)。如下例:
<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL"
Description="Generates a update stored procedure." %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema"
Category="Context"
Description="Table that the stored procedures should be based on." %>
<%@ Assembly Src="CommonUtility.cs" %>
<%@ Import Namespace="Common.Data" %>
<script runat="template">
CommonUtility rule=new CommonUtility();
</script>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using TonkNet.FrameWork.Business.Model;
using TonkNet.FrameWork.Business.Model.Attributes;
namespace TonkNet.KBS.Model
{
/// <summary>
/// <%= SourceTable.Name %> object for TFramework mapped table '<%= SourceTable.Name %>'.
/// </summary>
[Serializable]
[Table("<%= SourceTable.Name %>", "dbo")]
public class <%= SourceTable.Name %>
{
<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
protected <%= rule.GetCSharpVariableType(SourceTable.Columns[i]) %> _<%= SourceTable.Columns[i].Name %>;
<% } %>
public <%= SourceTable.Name %>() { }
<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
[Column("<%= SourceTable.Columns[i].Name %>", <%= rule.GetCSharpVariableType(SourceTable.Columns[i]) %>, <%= SourceTable.Columns[i].Size %>, PrimaryKey = <% if (SourceTable.PrimaryKey.MemberColumns.Count == 1 && SourceTable.Columns[i].IsPrimaryKeyMember) { %>true<% } else { %>false<% } %>)]
public string <%= rule.GetCamelCaseName(SourceTable.Columns[i].Name) %>
{
get { return _<%= SourceTable.Columns[i].Name %>; }
set { _<%= SourceTable.Columns[i].Name %> = value; }
}
<% } %>
}
}
这解释一下前面几行:
1. 第一行指名这是一个C#语言模板。
2. <%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>加载使用访问数据库的组建SchmaExplorer
3. 接下来表示变量类型为数据库的表,如果你在选择数据库对象时(后面介绍)时,选择的类型是视图,需要将变量类型Type中的SchemaExplorer.TableSchema修改为SchemaExplorer.ViewSchema。
4. <%@ Assembly Src="CommonUtility.cs" %>表示引入类CommonUtility.cs,如此我们便可以使用c#的方法来处理字符串了(比如,你需要将字段名首字母改为大些,该类的GetCamelCaseName(string)方法实现了。) 注意:CommonUtility.cs类(见附录)需要放到安装根目录下,如果路径不对,会提示你,某个文件下找不到这个类,将它copy进去即可。
5. <script>标签内的部分创建了CommonUtility.cs的类的实例。
模板using上面的部分,属于CodeSmith内部的定义,在生成Code时,不会被添加到文件中来。上面的模板可能有些凌乱,简化一下,大约是这个样子(下面的文件只表示文件的结构,模板不可以修改为它):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using TonkNet.FrameWork.Business.Model;
using TonkNet.FrameWork.Business.Model.Attributes;
namespace TonkNet.KBS.Model
{
/// <summary>
/// #table.name# object for TFramework mapped table '#table.name#'.
/// </summary>
[Serializable]
[Table("#table.name#", "dbo")]
public class #table.name#
{
// 循环取table里的字段名,来声明成员变量 CodeSmith里面<%=%>内为代码块(或数据、或函数)
protected #table.column[i].type# _#table.column[i].name#;
// 循环去table的字段,来定义属性
public #table.column[i].name#() { }
[Column("#table.column[i].name#", #table.column[i].type#, #table.column[i].size#, PrimaryKey = #table.column[i].name#.IsPrimaryKeyMember) true else false
public string #table.column[i].name#
{
get { return _#table.column[i].name#; }
set { #table.column[i].name# = value; }
}
}
}
设置好模板后,保存一下。
接下来,在属性栏中,选择数据库对象(表格),点击"..."按钮,弹出窗口:
接着,改是添加CommonUtility.cs添加进来的时候了,它包括一些数据库类型转c#类型、首字母大写的方法:
using System;
using System.Text;
using CodeSmith.Engine;
using SchemaExplorer;
using System.ComponentModel;
using System.Data;
namespace Common.Data
{
/**//// <summary>
/// TemplateRule
/// </summary>
public class CommonUtility
{
//get Columns info by TableName
public ColumnSchemaCollection GetColumnCollectionByTable(TableSchema table)
{
ColumnSchemaCollection columns=new ColumnSchemaCollection(table.Columns);
return columns;
}
//Get camelcase name,such as Customer,
public string GetCamelCaseName(string str)
{
return str.Substring(0,1).ToUpper()+str.Substring(1);
}
//Get ,user,private const String USER_FIELD = "User"
public string GetMemberConstantDeclarationStatement(ColumnSchema column)
{
return GetMemberConstantDeclarationStatement("public const String ",column);
}
//such as public const String USER_TABLE = "User"
public string GetTableConstantDeclarationStatement(TableSchema table)
{
return GetMemberConstantDeclarationStatement("public const String ",table);
}
//suck as USER_TABLE
public string GetUpperStatement(TableSchema table)
{
return table.Name.ToUpper()+"_TABLE";
}
//suck as USER_FIELD
public string GetUpperStatement(ColumnSchema column)
{
return column.Name.ToUpper()+"_FIELD";
}
// such as USER_TABLE = "User"
public string GetMemberConstantDeclarationStatement(string protectionLevel,TableSchema table)
{
return protectionLevel+GetUpperStatement(table)+" = ""+GetCamelCaseName(table.Name)+""";
}
//such as USERID_FIELD = "Userid"
public string GetMemberConstantDeclarationStatement(string protectionLevel,ColumnSchema column)
{
return protectionLevel+GetUpperStatement(column)+" = ""+GetCamelCaseName(column.Name)+""";
}
public string GetCSharpVariableType(ColumnSchema column)
{
switch(column.DataType)
{
case DbType.AnsiString: return "string";
case DbType.AnsiStringFixedLength: return "string";
case DbType.Binary: return "byte[]";
case DbType.Boolean: return "bool";
case DbType.Byte: return "int";
case DbType.Currency: return "decimal";
case DbType.Date: return "DataTime";
case DbType.DateTime: return "DateTime";
case DbType.Decimal: return "decimal";
case DbType.Double: return "double";
case DbType.Guid: return "Guid";
case DbType.Int16: return "short";
case DbType.Int32: return "int";
case DbType.Int64: return "long";
case DbType.Object: return "object";
case DbType.SByte: return "sbyte";
case DbType.Single: return "float";
case DbType.String: return "string";
case DbType.StringFixedLength: return "string";
case DbType.Time: return "TimeSpan";
case DbType.UInt16: return "ushort";
case DbType.UInt32: return "uint";
case DbType.UInt64: return "ulong";
case DbType.VarNumeric: return "decimal";
}
return null;
}
public string GetCSharpBaseType(ColumnSchema column)
{
switch(column.DataType)
{
case DbType.AnsiString: return "System.String";
case DbType.AnsiStringFixedLength: return "System.String";
case DbType.Binary: return "System.Byte[]";
case DbType.Boolean: return "System.Boolean";
case DbType.Byte: return "System.Int32";
case DbType.Currency: return "System.Decimal";
case DbType.Date: return "System.DataTime";
case DbType.DateTime: return "System.DataTime";
case DbType.Decimal: return "System.Decimal";
case DbType.Double: return "System.Double";
case DbType.Guid: return "System.Guid";
case DbType.Int16: return "System.Int16";
case DbType.Int32: return "System.Int32";
case DbType.Int64: return "System.Int64";
case DbType.Object: return "System.Object";
case DbType.SByte: return "System.SByte";
case DbType.Single: return "System.Single";
case DbType.String: return "System.String";
case DbType.StringFixedLength: return "System.String";
case DbType.Time: return "System.TimeSpan";
case DbType.UInt16: return "System.UInt16";
case DbType.UInt32: return "System.UInt32";
case DbType.UInt64: return "System.UInt64";
case DbType.VarNumeric: return "System.Decimal";
}
return null;
}
}
}
现在,点生成,你就能看到你想要的Model了,可能你需要修改类名(因为它们跟表名一致,而我一般命名表明,通常是"工程名缩写 + _ + 表的意义"。或者,你在CommonUtility.cs里面添加改名的方法)。
补充,CodeSmith中文教程链接:http://download.csdn.net/source/347104
为什么我们不将这件工作交给一个工具来完成呢?
CodeSmith是个很强大的Code生成工具,可以操作数据库、Collection(.net)集合类型等等,可生成c#、js、vb、HashTable、List、Query、Xml,自成一套语法规则。(Eclipse将这个生成工作集成到它的IDE里面去了,虽然没这么强大,当然,你写好模板还是可以生成java代码的)。它的工作原理很简单:读模板文件、用数据覆盖标记、写文件等等,只不过,它将添加了链接了数据库等功能,直接图形化操作,可设置断点调试,解释执行,方便Debug。
好吧,闲话不多少,我们开始本文的主体部分。
首先,你需要下载CodeSmith,并安装(网上有注册机,本文基于V3.2版本)。打开CodeSmith Studio,新建一个c#模板(菜单栏File->New->c# Template)。如下例:
<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL"
Description="Generates a update stored procedure." %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema"
Category="Context"
Description="Table that the stored procedures should be based on." %>
<%@ Assembly Src="CommonUtility.cs" %>
<%@ Import Namespace="Common.Data" %>
<script runat="template">
CommonUtility rule=new CommonUtility();
</script>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using TonkNet.FrameWork.Business.Model;
using TonkNet.FrameWork.Business.Model.Attributes;
namespace TonkNet.KBS.Model
{
/// <summary>
/// <%= SourceTable.Name %> object for TFramework mapped table '<%= SourceTable.Name %>'.
/// </summary>
[Serializable]
[Table("<%= SourceTable.Name %>", "dbo")]
public class <%= SourceTable.Name %>
{
<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
protected <%= rule.GetCSharpVariableType(SourceTable.Columns[i]) %> _<%= SourceTable.Columns[i].Name %>;
<% } %>
public <%= SourceTable.Name %>() { }
<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
[Column("<%= SourceTable.Columns[i].Name %>", <%= rule.GetCSharpVariableType(SourceTable.Columns[i]) %>, <%= SourceTable.Columns[i].Size %>, PrimaryKey = <% if (SourceTable.PrimaryKey.MemberColumns.Count == 1 && SourceTable.Columns[i].IsPrimaryKeyMember) { %>true<% } else { %>false<% } %>)]
public string <%= rule.GetCamelCaseName(SourceTable.Columns[i].Name) %>
{
get { return _<%= SourceTable.Columns[i].Name %>; }
set { _<%= SourceTable.Columns[i].Name %> = value; }
}
<% } %>
}
}
这解释一下前面几行:
1. 第一行指名这是一个C#语言模板。
2. <%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>加载使用访问数据库的组建SchmaExplorer
3. 接下来表示变量类型为数据库的表,如果你在选择数据库对象时(后面介绍)时,选择的类型是视图,需要将变量类型Type中的SchemaExplorer.TableSchema修改为SchemaExplorer.ViewSchema。
4. <%@ Assembly Src="CommonUtility.cs" %>表示引入类CommonUtility.cs,如此我们便可以使用c#的方法来处理字符串了(比如,你需要将字段名首字母改为大些,该类的GetCamelCaseName(string)方法实现了。) 注意:CommonUtility.cs类(见附录)需要放到安装根目录下,如果路径不对,会提示你,某个文件下找不到这个类,将它copy进去即可。
5. <script>标签内的部分创建了CommonUtility.cs的类的实例。
模板using上面的部分,属于CodeSmith内部的定义,在生成Code时,不会被添加到文件中来。上面的模板可能有些凌乱,简化一下,大约是这个样子(下面的文件只表示文件的结构,模板不可以修改为它):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using TonkNet.FrameWork.Business.Model;
using TonkNet.FrameWork.Business.Model.Attributes;
namespace TonkNet.KBS.Model
{
/// <summary>
/// #table.name# object for TFramework mapped table '#table.name#'.
/// </summary>
[Serializable]
[Table("#table.name#", "dbo")]
public class #table.name#
{
// 循环取table里的字段名,来声明成员变量 CodeSmith里面<%=%>内为代码块(或数据、或函数)
protected #table.column[i].type# _#table.column[i].name#;
// 循环去table的字段,来定义属性
public #table.column[i].name#() { }
[Column("#table.column[i].name#", #table.column[i].type#, #table.column[i].size#, PrimaryKey = #table.column[i].name#.IsPrimaryKeyMember) true else false
public string #table.column[i].name#
{
get { return _#table.column[i].name#; }
set { #table.column[i].name# = value; }
}
}
}
设置好模板后,保存一下。
接下来,在属性栏中,选择数据库对象(表格),点击"..."按钮,弹出窗口:
接着,改是添加CommonUtility.cs添加进来的时候了,它包括一些数据库类型转c#类型、首字母大写的方法:
using System;
using System.Text;
using CodeSmith.Engine;
using SchemaExplorer;
using System.ComponentModel;
using System.Data;
namespace Common.Data
{
/**//// <summary>
/// TemplateRule
/// </summary>
public class CommonUtility
{
//get Columns info by TableName
public ColumnSchemaCollection GetColumnCollectionByTable(TableSchema table)
{
ColumnSchemaCollection columns=new ColumnSchemaCollection(table.Columns);
return columns;
}
//Get camelcase name,such as Customer,
public string GetCamelCaseName(string str)
{
return str.Substring(0,1).ToUpper()+str.Substring(1);
}
//Get ,user,private const String USER_FIELD = "User"
public string GetMemberConstantDeclarationStatement(ColumnSchema column)
{
return GetMemberConstantDeclarationStatement("public const String ",column);
}
//such as public const String USER_TABLE = "User"
public string GetTableConstantDeclarationStatement(TableSchema table)
{
return GetMemberConstantDeclarationStatement("public const String ",table);
}
//suck as USER_TABLE
public string GetUpperStatement(TableSchema table)
{
return table.Name.ToUpper()+"_TABLE";
}
//suck as USER_FIELD
public string GetUpperStatement(ColumnSchema column)
{
return column.Name.ToUpper()+"_FIELD";
}
// such as USER_TABLE = "User"
public string GetMemberConstantDeclarationStatement(string protectionLevel,TableSchema table)
{
return protectionLevel+GetUpperStatement(table)+" = ""+GetCamelCaseName(table.Name)+""";
}
//such as USERID_FIELD = "Userid"
public string GetMemberConstantDeclarationStatement(string protectionLevel,ColumnSchema column)
{
return protectionLevel+GetUpperStatement(column)+" = ""+GetCamelCaseName(column.Name)+""";
}
public string GetCSharpVariableType(ColumnSchema column)
{
switch(column.DataType)
{
case DbType.AnsiString: return "string";
case DbType.AnsiStringFixedLength: return "string";
case DbType.Binary: return "byte[]";
case DbType.Boolean: return "bool";
case DbType.Byte: return "int";
case DbType.Currency: return "decimal";
case DbType.Date: return "DataTime";
case DbType.DateTime: return "DateTime";
case DbType.Decimal: return "decimal";
case DbType.Double: return "double";
case DbType.Guid: return "Guid";
case DbType.Int16: return "short";
case DbType.Int32: return "int";
case DbType.Int64: return "long";
case DbType.Object: return "object";
case DbType.SByte: return "sbyte";
case DbType.Single: return "float";
case DbType.String: return "string";
case DbType.StringFixedLength: return "string";
case DbType.Time: return "TimeSpan";
case DbType.UInt16: return "ushort";
case DbType.UInt32: return "uint";
case DbType.UInt64: return "ulong";
case DbType.VarNumeric: return "decimal";
}
return null;
}
public string GetCSharpBaseType(ColumnSchema column)
{
switch(column.DataType)
{
case DbType.AnsiString: return "System.String";
case DbType.AnsiStringFixedLength: return "System.String";
case DbType.Binary: return "System.Byte[]";
case DbType.Boolean: return "System.Boolean";
case DbType.Byte: return "System.Int32";
case DbType.Currency: return "System.Decimal";
case DbType.Date: return "System.DataTime";
case DbType.DateTime: return "System.DataTime";
case DbType.Decimal: return "System.Decimal";
case DbType.Double: return "System.Double";
case DbType.Guid: return "System.Guid";
case DbType.Int16: return "System.Int16";
case DbType.Int32: return "System.Int32";
case DbType.Int64: return "System.Int64";
case DbType.Object: return "System.Object";
case DbType.SByte: return "System.SByte";
case DbType.Single: return "System.Single";
case DbType.String: return "System.String";
case DbType.StringFixedLength: return "System.String";
case DbType.Time: return "System.TimeSpan";
case DbType.UInt16: return "System.UInt16";
case DbType.UInt32: return "System.UInt32";
case DbType.UInt64: return "System.UInt64";
case DbType.VarNumeric: return "System.Decimal";
}
return null;
}
}
}
现在,点生成,你就能看到你想要的Model了,可能你需要修改类名(因为它们跟表名一致,而我一般命名表明,通常是"工程名缩写 + _ + 表的意义"。或者,你在CommonUtility.cs里面添加改名的方法)。
补充,CodeSmith中文教程链接:http://download.csdn.net/source/347104
相关文章推荐
- 使用CodeSmith生成oracle数据库表的实体层(Model) ——来自 dacong
- 使用CodeSmith生成oracle数据库表的实体层(Model)
- 使用CodeSmith生成oracle数据库表的实体层(Model)
- 如何使用CodeSmith自动生成C#代码
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库。
- TestNG如何修改运行结果(通过使用监听器和报表器,可以很轻松的生成自己的TestNG报表)
- 使用dtree生成的树结构,ajax动态加载子节点后,如何绑定右键菜单续
- 如何生成.so和.a文件及使用
- 使用mybatis-generator自动生成model、dao、mapping文件
- JSP设计模式基础:View Helper模式——学习如何使用View Helper模式使得Model数据适应表现层的需要(2)
- 如何生成Detours.lib——Detours的使用准备
- 如何理解Vue的v-model指令的使用方法
- 使用sublime text2如何新建文件快速生成HTML头部信息?
- 如何使用Cocos2D 2.X生成一个简单的iPhone游戏 (2/8)
- 在Linux下如何使用GCC编译程序、简单生成静态库及动态库。
- webp如何使用,webp是什么?webp如何生成,
- 如何利用深度学习写诗歌(使用Python进行文本生成)
- 在gradle中使用MyBatis Generator生成model,dao,mapper
- 如何使用ADO助手生成数据库代码
- JSP设计模式基础:View Helper模式——学习如何使用View Helper模式使得Model数据适应表现层的需要(3)