CodeSmith(4):创建实体类实例
利用SchemaExplorer中的类:TableSchema,ColumnSchema来制造一个实体类。
首先我们得了解实体类的构成,一般的实体类由私有字段和公开方法组成,例如下面的类:
using System;
using System.Collections.Generic;
using System.Text;
namespace com.xaccp.Entity
{
public class Person
{
private string name;
private bool sex;
private int age;
public string Name
{
get { return name; }
set { name = value; }
}
,,,,,
}
}
实体类中的字段应该和数据库中的字段相同,只是类型要从Sql中的数据类型变为C#中的数据类型,一般实体类中的字段的名字可以采用与数据库中字段的名称相同,只不过字段名一般采用骆驼命名法,属性名称一般采用Pascal命名法。
私有字段部分有些内容是永远不变的,字段的访问修饰符永远为“private”,字段的结尾永远为“;”;变化的部分为,每个字段根据数据库中的类型变化为C#中的类型,字段的名称也是变化的。
公开字段中也有内容为永远不变的
public 数据类型 属性名称
{
get { return 字段名称; }
set { 字段名称 = value; }
}
第一个模板
<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="" Inherits="" Debug="False" Description="产生实体类" ResponseEncoding="UTF-8" %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Default="" Optional="False" Category="Context" Description="源表名" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Assembly Name="System.Data" %>
<%@ Import Namespace="System.Data" %>
using System;
namespace com.xaccp.Entity
{
public class Person
{
//这里的内容为私有字段和公开属性。
<%foreach(ColumnSchema column in this.SourceTable.Columns)%>
<%{%>
private <%=column.SystemType%> <%=column.Name%>;
<%}%>
<%foreach(ColumnSchema column in this.SourceTable.Columns)%>
<%{%>
public <%=column.SystemType%> <%=column.Name%>
{
get{return <%=column.Name%>;}
set{<%=column.Name%>=value;}
}
<%}%>
}
}
所产生的实体类问题?
第一:所产生的这个类,根本编译不过去。
第二:这个类的类名永远是Person,即使产生了这个类,还得修改。
第三:命名空间也要改。
第四:……
错误提示在title_id这个属性那里。原来是字段名称和属性名称冲突了,正确的应该是字段名称使用骆驼命名法,而属性用Pascal命名法。只需要将字段的第一个字母改为小写,属性的第一个字母改为大写。
写一个公共函数
//以骆驼命名法格式化字符串
public string ToCamel(string s)
{
return s.Substring(0,1).ToLower()+s.Substring(1);
}
//以Pascal命名法格式化字符串
public string ToPascal(string s)
{
return s.Substring(0,1).ToUpper()+s.Substring(1);
}
更改输出的代码段:
//字段部分
private <%=column.SystemType%> <%=ToCamel(column.Name)%>;
//属性部分
public <%=column.SystemType%> <%=ToPascal(column.Name)%>
{
get{return <%=ToCamel(column.Name)%>;}
get{<%=ToCamel(column.Name)%>=value;}
}
类名变化
最好让类名和表名有关系。表名能不能来做类名呢?因为表名通常为复数形式,能不能改成单数啊?只要去掉表名后的“s”
public string GetClassName(TableSchema table)
{
string s=table.Name;
if(s.Substring(s.Length-1)=="s")
{
return ToPascal(s.Substring(0,s.Length-1));
}
return ToPascal(s);
}
class <%=GetClassName(this.SourceTable)%>
命名空间
一般情况下,都将命名空间设置为Model或者Entity,可是到底选择哪一个什么?
在声明部分添加:
<%@ Property Name="NameSpace" Type="System.String" Default="Model" Optional="False" Category="" Description="" Editor="" EditorBase="" Serializer="" %>
namespace <%=NameSpace%>
类型问题
private <%=column.SystemType%> <%=ToCamel(column.Name)%>;
“System.String”和“string”都是一回事,我们写的程序毕竟不是用MSIL语言写的,是用C#,最好别用CTS中的数据类型?
解决的函数如下:
public string GetCSDataType(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 "byte";
case DbType.Currency: return "decimal";
case DbType.Date: return "DateTime";
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";
default:
{
return "__UNKNOWN__" + column.NativeType;
}
}
}
无论是从列结构上获取的SystemType还是DataType属性,都是用来表达这个列的数据类型的,尽管他们分别是CTS和SQL中的数据类型,从CTS转换和从SQL转换,有什么本质差别不?可是DataType是个枚举类型的属性,如果在VS.Net2005中,一旦switch一个枚举变量,可以自动生成这个枚举类型中所有的枚举值的case分支,这样,咱们只需要填写case的结构就可以了。