用 StringTemplate重新制作代码生成工具
2011-07-24 02:14
411 查看
放假没事干,重做了一下以前做的代码生成工具(在《基于CodeSmith的数据处理代码生成工具》中提到),正确来说,以前的是CodeSmith的模板,必须安装该软件才能使用,很不爽。(文/Stephen.Huang)
这次用StringTemplate来生成模板,而自己则负责写以前CodeSmith负责做的东西,如获取数据库,表,列的Schema,并封装成一个一个类。
制作这个代码生成工具时,考虑到的和遇到的一些问题总结一下:
1.必需适应各种不同的数据库
a)使用DbProviderFactory来创建各种对象,如DbParameter。想起以前一直都是hardcode SqlParameter。DbProviderFactory会根据数据库驱动的不同,创建不同的对象,如 providerName="System.Data.SqlClient"时,用 DbProviderFactory.CreateParameter,会创建SqlParameter类型的对象。
b)把MS的SqlHelper改写(不知道是不是MS写的),全部改写成System.Data.Common下的数据库对象(DbProviderFactory Create出来的对象,用DbType而不用SqlDbType),并只保留一些常用的方法(事实上是全部改写很麻烦),如 PrepareParameter,ExecuteReader,ExecuteNonQuery,ExecuteDataSet(ExecuteDataSet 还是尽量避免使用的,留下来以防万一)。
c)在获取Schema时遇到的问题-命名规范:Select * from 表名,表名中出现保留字时,不同的数据库可能不一样,比较难解决,不同的数据库解决方法可能不同。SqlServer中需要为表名加上"[]"(如果表名中包含了"["或"]"中任意一个,还需要特殊处理,自己一般不会这样来给表命名,忽略- -)。
d)在获取Schema时遇到的问题2:当SQL2005里面遇到视图如[HumanResouce].[vEmployee],则 select * from vEmployee无效,必须要select * from [HumanResouce].[vEmployee],不知道其他数据库是什么情况- -看来要做成通用的,真的很难,还是以后根据实际情况再改吧:)
e)使用DbDataReader.GetSchemaTable才会遇到上述c、d这两个需要写sql才能获取schema的问题。还有一种方法是使用DbConnection.GetSchema来获取字段的信息,但是此方法比较繁琐,本人尚未成功地获取Primary key和identity Column等的详细信息(T_T),有空再研究研究。
f)从数据库中取出的原始信息,为适应各种数据库建立不同TableWrapper和CoumnWrapper(即使用原始信息对不同数据库进行封装),对不同的程语编言建立各种别名(如用CSharpAlias类能够把System.Int32转变成int),对不同的数据库创建不同的 sql模板(有待完成)。
2.使用何种模板引擎
这里选择了StringTemplate。为什么?因为学习简单,使用也简单,功能很强大。当使用 stringTemplate.SetAttribute("pkColumns", tableWrapper.PkColumns); 后,可以在模板里访问PkColumns里面的public Field和Property。包含判断和循环的语法。支持嵌套模板。
还差一个可视化使用界面,懒,暂时先将就使用一下- -
附上模板的代码:(下载地址)using System;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Collections.Generic;
namespace
{
public class $table.EntityName$Dao
{
private static ConnectionStringSettings dbSettings = DataConnection.;
private static string connectionString = dbSettings.ConnectionString;
private static DbProviderFactory dbFactory = DbProviderFactories.GetFactory(dbSettings.ProviderName);
public static List<$table.EntityName[ DISCUZ_CODE_1 ]gt; GetAll()
{
var list = new List<$table.EntityName[ DISCUZ_CODE_1 ]gt;();
DbDataReader dr = null;
try
{
dr = SqlHelper.ExecuteReader(dbFactory, connectionString
, CommandType.Text
, "select $allColumns:{$it.QualifiedColumnName$};separator=","$ from $table.QualifiedTableName[ DISCUZ_CODE_2 ]quot;);
while (dr != null && dr.Read())
{
var obj = new $table.EntityName$();
$allColumns:{obj.$it.PropName$ = Field.Get$it.SystemTypeShortName$(dr, "$it.Name[ DISCUZ_CODE_2 ]quot;);};separator="\r\n"$
list.Add(obj);
}
}
finally
{
if (dr != null)
{
dr.Close();
dr.Dispose();
}
}
return list;
}$if(table.IsTable)$
public static $table.EntityName$ Get($pkColumns:{$it.SystemType$ $it.VarName$};separator=","$)
{
$table.EntityName$ obj = null;
DbDataReader dr = null;
try
{
var paras = new DbParameter[]{
$pkColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, $it.VarName$)};separator=",\r\n"$
};
dr = SqlHelper.ExecuteReader(dbFactory, connectionString
, CommandType.Text
, "select $allColumns:{$it.QualifiedColumnName$};separator=","$ from $table.QualifiedTableName$ where $pkColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator="and "[ DISCUZ_CODE_2 ]quot;, paras);
if (dr != null && dr.Read())
{
obj = new $table.EntityName$();
$allColumns:{obj.$it.PropName$ = Field.Get$it.SystemTypeShortName$(dr, "$it.Name[ DISCUZ_CODE_2 ]quot;);};separator="\r\n"$
}
}
finally
{
if (dr != null)
{
dr.Close();
dr.Dispose();
}
}
return obj;
}
public static bool Insert($table.EntityName$ obj)
{
bool flag = false;
try
{
var paras = new DbParameter[]{
$nonIdColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, obj.$it.PropName$)};separator=",\r\n"$
};
SqlHelper.ExecuteNonQuery(dbFactory, connectionString
, CommandType.Text
, "insert into $table.QualifiedTableName$($nonIdColumns:{$it.QualifiedColumnName$};separator=", "$) values($nonIdColumns:{@$it.PropName$};separator=", "$)", paras);
flag = true;
}
catch (Exception)
{
flag = false;
}
return flag;
}
public static bool Update($table.EntityName$ obj)
{
bool flag = false;
try
{
var paras = new DbParameter[]{
$allColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, obj.$it.PropName$)};separator=",\r\n"$
};
SqlHelper.ExecuteNonQuery(dbFactory, connectionString
, CommandType.Text
, "update $table.QualifiedTableName$ set $updateColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator=", "$ where $pkColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator="and "[ DISCUZ_CODE_2 ]quot;, paras);
flag = true;
}
catch (Exception)
{
flag = false;
}
return flag;
}
public static bool Delete($pkColumns:{$it.SystemType$ $it.VarName$};separator=","$)
{
bool flag = false;
try
{
var paras = new DbParameter[]{
$pkColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, $it.VarName$)};separator=",\r\n"$
};
SqlHelper.ExecuteNonQuery(dbFactory, connectionString
, CommandType.Text
, "delete from $table.QualifiedTableName$ where $pkColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator="and "[ DISCUZ_CODE_2 ]quot;, paras);
flag = true;
}
catch (Exception)
{
flag = false;
}
return flag;
}$endif$
}
}
复制代码
这次用StringTemplate来生成模板,而自己则负责写以前CodeSmith负责做的东西,如获取数据库,表,列的Schema,并封装成一个一个类。
制作这个代码生成工具时,考虑到的和遇到的一些问题总结一下:
1.必需适应各种不同的数据库
a)使用DbProviderFactory来创建各种对象,如DbParameter。想起以前一直都是hardcode SqlParameter。DbProviderFactory会根据数据库驱动的不同,创建不同的对象,如 providerName="System.Data.SqlClient"时,用 DbProviderFactory.CreateParameter,会创建SqlParameter类型的对象。
b)把MS的SqlHelper改写(不知道是不是MS写的),全部改写成System.Data.Common下的数据库对象(DbProviderFactory Create出来的对象,用DbType而不用SqlDbType),并只保留一些常用的方法(事实上是全部改写很麻烦),如 PrepareParameter,ExecuteReader,ExecuteNonQuery,ExecuteDataSet(ExecuteDataSet 还是尽量避免使用的,留下来以防万一)。
c)在获取Schema时遇到的问题-命名规范:Select * from 表名,表名中出现保留字时,不同的数据库可能不一样,比较难解决,不同的数据库解决方法可能不同。SqlServer中需要为表名加上"[]"(如果表名中包含了"["或"]"中任意一个,还需要特殊处理,自己一般不会这样来给表命名,忽略- -)。
d)在获取Schema时遇到的问题2:当SQL2005里面遇到视图如[HumanResouce].[vEmployee],则 select * from vEmployee无效,必须要select * from [HumanResouce].[vEmployee],不知道其他数据库是什么情况- -看来要做成通用的,真的很难,还是以后根据实际情况再改吧:)
e)使用DbDataReader.GetSchemaTable才会遇到上述c、d这两个需要写sql才能获取schema的问题。还有一种方法是使用DbConnection.GetSchema来获取字段的信息,但是此方法比较繁琐,本人尚未成功地获取Primary key和identity Column等的详细信息(T_T),有空再研究研究。
f)从数据库中取出的原始信息,为适应各种数据库建立不同TableWrapper和CoumnWrapper(即使用原始信息对不同数据库进行封装),对不同的程语编言建立各种别名(如用CSharpAlias类能够把System.Int32转变成int),对不同的数据库创建不同的 sql模板(有待完成)。
2.使用何种模板引擎
这里选择了StringTemplate。为什么?因为学习简单,使用也简单,功能很强大。当使用 stringTemplate.SetAttribute("pkColumns", tableWrapper.PkColumns); 后,可以在模板里访问PkColumns里面的public Field和Property。包含判断和循环的语法。支持嵌套模板。
还差一个可视化使用界面,懒,暂时先将就使用一下- -
附上模板的代码:(下载地址)using System;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Collections.Generic;
namespace
{
public class $table.EntityName$Dao
{
private static ConnectionStringSettings dbSettings = DataConnection.;
private static string connectionString = dbSettings.ConnectionString;
private static DbProviderFactory dbFactory = DbProviderFactories.GetFactory(dbSettings.ProviderName);
public static List<$table.EntityName[ DISCUZ_CODE_1 ]gt; GetAll()
{
var list = new List<$table.EntityName[ DISCUZ_CODE_1 ]gt;();
DbDataReader dr = null;
try
{
dr = SqlHelper.ExecuteReader(dbFactory, connectionString
, CommandType.Text
, "select $allColumns:{$it.QualifiedColumnName$};separator=","$ from $table.QualifiedTableName[ DISCUZ_CODE_2 ]quot;);
while (dr != null && dr.Read())
{
var obj = new $table.EntityName$();
$allColumns:{obj.$it.PropName$ = Field.Get$it.SystemTypeShortName$(dr, "$it.Name[ DISCUZ_CODE_2 ]quot;);};separator="\r\n"$
list.Add(obj);
}
}
finally
{
if (dr != null)
{
dr.Close();
dr.Dispose();
}
}
return list;
}$if(table.IsTable)$
public static $table.EntityName$ Get($pkColumns:{$it.SystemType$ $it.VarName$};separator=","$)
{
$table.EntityName$ obj = null;
DbDataReader dr = null;
try
{
var paras = new DbParameter[]{
$pkColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, $it.VarName$)};separator=",\r\n"$
};
dr = SqlHelper.ExecuteReader(dbFactory, connectionString
, CommandType.Text
, "select $allColumns:{$it.QualifiedColumnName$};separator=","$ from $table.QualifiedTableName$ where $pkColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator="and "[ DISCUZ_CODE_2 ]quot;, paras);
if (dr != null && dr.Read())
{
obj = new $table.EntityName$();
$allColumns:{obj.$it.PropName$ = Field.Get$it.SystemTypeShortName$(dr, "$it.Name[ DISCUZ_CODE_2 ]quot;);};separator="\r\n"$
}
}
finally
{
if (dr != null)
{
dr.Close();
dr.Dispose();
}
}
return obj;
}
public static bool Insert($table.EntityName$ obj)
{
bool flag = false;
try
{
var paras = new DbParameter[]{
$nonIdColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, obj.$it.PropName$)};separator=",\r\n"$
};
SqlHelper.ExecuteNonQuery(dbFactory, connectionString
, CommandType.Text
, "insert into $table.QualifiedTableName$($nonIdColumns:{$it.QualifiedColumnName$};separator=", "$) values($nonIdColumns:{@$it.PropName$};separator=", "$)", paras);
flag = true;
}
catch (Exception)
{
flag = false;
}
return flag;
}
public static bool Update($table.EntityName$ obj)
{
bool flag = false;
try
{
var paras = new DbParameter[]{
$allColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, obj.$it.PropName$)};separator=",\r\n"$
};
SqlHelper.ExecuteNonQuery(dbFactory, connectionString
, CommandType.Text
, "update $table.QualifiedTableName$ set $updateColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator=", "$ where $pkColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator="and "[ DISCUZ_CODE_2 ]quot;, paras);
flag = true;
}
catch (Exception)
{
flag = false;
}
return flag;
}
public static bool Delete($pkColumns:{$it.SystemType$ $it.VarName$};separator=","$)
{
bool flag = false;
try
{
var paras = new DbParameter[]{
$pkColumns:{SqlHelper.PrepareParameter(dbFactory, "$it.Name[ DISCUZ_CODE_2 ]quot;, $it.DBType$, $it.VarName$)};separator=",\r\n"$
};
SqlHelper.ExecuteNonQuery(dbFactory, connectionString
, CommandType.Text
, "delete from $table.QualifiedTableName$ where $pkColumns:{$it.QualifiedColumnName$=@$it.PropName$};separator="and "[ DISCUZ_CODE_2 ]quot;, paras);
flag = true;
}
catch (Exception)
{
flag = false;
}
return flag;
}$endif$
}
}
复制代码
相关文章推荐
- 用StringTemplate重新制作代码生成工具
- CLIP PATH (MASK) GENERATOR是一款在线制作生成clip-path路径的工具,可以直接生成SVG代码以及配合Mask制作蒙板。
- CSS Animatie是一款在线制作CSS3动画的工具,可以在线直接制作CSS3动画效果,生成代码
- 使用HTML+Javascript制作代码生成工具
- uiCoder界面代码生成工具 part1 概述+图片制作
- Ibatis代码自动生成工具
- T4+VSIX打造VS2010代码生成自定义工具
- 发布Oracle存储过程包c#代码生成工具(CodeRobot)
- VS代码生成工具ReSharper使用手册:配置快捷键
- [CSS工具推荐]0001.推荐 10 个超棒的 CSS3 代码生成工具
- mybatis 代码生成工具的使用
- 强大的代码生成工具MyGeneration
- MyBatis代码生成工具mybatis-generator在Myeclipse10中的使用
- PxCook 高效智能的研发设计工具。点击设计稿即可生成前端代码的智能标注切图软件
- PHP 自动生成帮助文档工具1.0Beta版【代码维护神器】
- 制作原型的工具重新回归Gui Design Studio
- carbon- 一个能生成漂亮的代码分享图的在线工具
- java代码生成工具之autoCode部署
- 如何利用NB代码生成工具和NBear框架,快速开发WEB项目
- Html5系列(十二)canvas-js贝塞尔曲线代码在线生成工具