按照开发层次来说,《用T4模版生成MyBatis映射文件代码》应该在前面介绍,但为了能够给大家简单介绍T4模版的使用,我把复杂的映射文件放在后面,以免大家产生畏难情绪而不使用俯在微软上的东东。
通过前面几篇文章,大家可以看到,我们使用的T4模版以及EF使非常简单的:
1、T4模版,就一对<# 和#>特殊运算符,其余的就是基本的时基础的语法了。
2、EF,我们使用了几个个属性:
A、EF的对象集合EdmItemCollection,从而获得实体集ItemCollection.GetItems<EntityType>();
B、EF的文件操作,主要是文件的输出:
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
fileManager.StartNewFile(文件名称);
C、EF中实体的属性的类型,edmProperty.TypeUsage以及转换code.Escape();
D、EF中实体的属性的名称,edmProperty.Name;
有了以上的,我们可以编写一些简单的、富有规律的模版,生成相应的代码。可这些还是不够的,还有一类属性我们没有介绍,导航属性;对,就是对象间的关系,再说来就是数据库的外键关系。关于外键的,我准备单独一篇文章介绍,因为它又是一个体系的东西了。
下面,我们开始《用T4模版生成MyBatis映射文件代码》编写。
第一步、在“解决方案JavaGenerate”中添加类库,用于存放SQLXml的模版及相应文件,我们命名这个类库为JavaSQLXmls。
点击“解决方案JavaGenerate”,右键,选择“添加 ”--〉“新建项目”,再选择"类库",名称中输入JavaSQLXmls。
返回后,在“解决方案JavaGenerate”中增加了一个叫JavaSQLXmls的项目,且自带了一个class.cs的类,我们点击它,
再点右键删除它,不用它。
如图7-1,注意红色方框,特别是要选中.NET Framework4
图7-1
第二步,增加t4空模版
在解决方案管理器中,选择JavaSQLXmls项目,点击右键,选择“添加 ”--〉“新建项”,
在弹出的窗体中做图6-2的选择和输入项
图6-2
第三步,我又贴代码,大家看注释把,没得错,我调试了的
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE"#>
<#@ output extension=".cs"#><#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
string inputFile = @"..\EDMX\dblxh.edmx";//EDMX项目中dblxh.edmx的路径
MetadataWorkspace metadataWorkspace = null;
bool allMetadataLoaded =loader.TryLoadAllMetadata(inputFile, out metadataWorkspace);
EdmItemCollection ItemCollection = (EdmItemCollection)metadataWorkspace.GetItemCollection(DataSpace.CSpace);
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
// 发出文件
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
string filePascialName=getModelsPascialName(entity.Name);//Pascial风格的类名称
string fileCamelName=getModelsCamelName(entity.Name);//Camel风格的类名称
string PrimaryPropertyPascialName="";//主键属性名称,Pascial风格的
string PrimaryPropertyCamelName="";//主键属性名称,Camel风格的
string PrimaryColumName="";//主键字段名称
fileManager.StartNewFile(filePascialName+ "Mapper.xml");//输出的类文件名称,及开始输出文件
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
if (ef.IsKey(edmProperty))
{
PrimaryPropertyPascialName=getPropertyPascialName(edmProperty.Name);
PrimaryPropertyCamelName=getPropertyCamelName(edmProperty.Name);
PrimaryColumName=edmProperty.Name;
break;
}
}
#>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--这个和我们的dao接口类的名称相同-->
<!--每次只需要修改包名-->
<mapper namespace="com.jiahe.rest.demo2.dao.<#=filePascialName#>Mapper">
<!-- 开启缓存。数据库的所有操作都通过这个底层进行操作,可以打开缓存,否则可能一直读取的都是脏数据 -->
<!-- 字段映射文件 -->
<resultMap id="m<#=filePascialName#>" type="<#=filePascialName#>">
<id column="<#=PrimaryColumName#>" property="<#=PrimaryPropertyPascialName#>"/>
<#foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
if (edmProperty.Name==PrimaryColumName) continue;
#>
<result column="<#=edmProperty.Name#>" property="<#=getPropertyCamelName(edmProperty.Name)#>"/>
<#}#>
</resultMap>
<!-- insert 增加,注意数据库的名称以及子增长字段的赋值,然后再回传给上层对象-->
<insert id="insert" parameterType="<#=filePascialName#>">
insert into dblxh.<#=entity.Name#>
(
<#=strInsertOneFormEntityProperty(entity)#>
)
values
(
<#= strInsert2(entity) #>
)
<selectKey resultType="Long" order="AFTER" keyProperty="<#=PrimaryPropertyCamelName#>">
SELECT LAST_INSERT_ID() AS id
</selectKey>
</insert>
<!-- update 修改,注意set以及if test的使用从而有值的才修改-->
<update id="update" parameterType="<#=filePascialName#>">
update dblxh.<#=entity.Name#>
<set>
<#foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
if (edmProperty.Name==PrimaryColumName) continue;
if ((edmProperty.Name=="create_time")||(edmProperty.Name=="create_author")) continue;//这两个字段,在修改时不修改;其它的不修改的字段如法炮制
if (edmProperty.Name=="update_time")
{#>
update_time=now(),
<# continue;
}
//if test进行分类判断处理,数值和字符串判断的不同
if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="Integer")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null"><#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>},</if>
<#}#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="Long")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null"><#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>},</if>
<#}#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="Double")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null"><#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>},</if>
<#}#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="String")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null and <#=getPropertyCamelName(edmProperty.Name)#> != ''"><#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>},</if>
<#}#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="byte[]")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null"><#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>},</if>
<#}#>
<#}#>
</set>
<where>
<#=PrimaryColumName#>=#{<#=PrimaryPropertyCamelName#>}
</where>
</update>
<!-- deleteByCondition 条件删除-->
<delete id="deleteByCondition" parameterType="<#=filePascialName#>" >
delete from dblxh.<#=entity.Name#>
<include refid="ifWhere"/>
</delete>
<!-- deleteByID 删除-->
<delete id="deleteByID" parameterType="<#=filePascialName#>" >
delete from dblxh.<#=entity.Name#>
where <#=PrimaryColumName#>=#{<#=PrimaryPropertyCamelName#>}
</delete>
<!-- findByID 主键查询-->
<select id="findByID" resultMap="m<#=filePascialName#>" parameterType="<#=filePascialName#>">
select * from dblxh.<#=entity.Name#>
where <#=PrimaryColumName#>=#{<#=PrimaryPropertyCamelName#>}
</select>
<!-- findByCondition 条件查询-->
<select id="findByCondition" resultMap="m<#=filePascialName#>" parameterType="<#=filePascialName#>">
select * from dblxh.<#=entity.Name#>
<include refid="ifWhere"/>
</select>
<!-- findCountByCondition 条件的数量-->
<select id="findCountByCondition" resultType="Long" parameterType="<#=filePascialName#>">
select count(*) from dblxh.<#=entity.Name#>
<include refid="ifWhere"/>
</select>
<!-- ifWhere-->
<sql id="ifWhere">
<where>
<#foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="Integer")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null and <#=getPropertyCamelName(edmProperty.Name)#>!=0">and <#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>}</if>
<#}#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="Long")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null and <#=getPropertyCamelName(edmProperty.Name)#>!=0">and <#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>}</if>
<#}#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="Double")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null and <#=getPropertyCamelName(edmProperty.Name)#>!=0">and <#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>}</if>
<#}#>
<#if (getPropertyType(code.Escape(edmProperty.TypeUsage))=="String")
{#>
<if test="<#=getPropertyCamelName(edmProperty.Name)#>!=null and <#=getPropertyCamelName(edmProperty.Name)#>!=''">and <#=edmProperty.Name#>=#{<#=getPropertyCamelName(edmProperty.Name)#>}</if>
<#}#>
<#}#>
</where>
</sql>
</mapper>
<#
}
fileManager.Process();
#>
<#+
//得到类的Pascial风格名称
string getModelsPascialName(string source)
{
string[] s=source.Split('_');
for(int i=0;i<s.Length;i++)
{
string s1=s[i].Substring(0,1).ToUpper();
string s2=s[i].Substring(1);
s[i]=string.Concat(s1,s2);
}
string result=string.Empty;
for(int i=1;i<s.Length;i++)
{
result=string.Concat(result,s[i]);
}
return result;
}
#>
<#+
//得到类的Camel风格名称
string getModelsCamelName(string source)
{
string[] s=source.Split('_');
for(int i=0;i<s.Length;i++)
{
string s1=s[i].Substring(0,1).ToUpper();
string s2=s[i].Substring(1);
s[i]=string.Concat(s1,s2);
}
string result=string.Empty;
for(int i=1;i<s.Length;i++)
{
result=string.Concat(result,s[i]);
}
string s11=result.Substring(0,1).ToLower();
string s12=result.Substring(1);
return string.Concat(s11,s12);
}
#>
<#+
//得到属性的Pascial风格名称
string getPropertyPascialName(string source)
{
string[] s=source.Split('_');
for(int i=0;i<s.Length;i++)
{
string s1=s[i].Substring(0,1).ToUpper();
string s2=s[i].Substring(1);
s[i]=string.Concat(s1,s2);
}
return string.Concat(s);
}
//得到属性的Camel风格名称
string getPropertyCamelName(string source)
{
string[] s=source.Split('_');
for(int i=0;i<s.Length;i++)
{
string s1=s[i].Substring(0,1).ToUpper();
string s2=s[i].Substring(1);
s[i]=string.Concat(s1,s2);
}
string result=string.Concat(s);
string s11=result.Substring(0,1).ToLower();
string s12=result.Substring(1);
return string.Concat(s11,s12);
}
//数据类型转换
string getPropertyType(string source)
{
string result=string.Empty;
if (source=="int") result="Integer";
if (source=="integer") result="Integer";
if (source=="Integer") result="Integer";
if (source=="byte") result="Integer";
if (source=="sbyte") result="Integer";
if (source=="bool") result="Integer";
if (source=="Int16") result="Integer";
if (source=="short") result="Integer";
if (source=="Int32") result="Integer";
if (source=="Nullable<int>") result="Integer";
if (source=="Nullable<integer>") result="Integer";
if (source=="Nullable<Integer>") result="Integer";
if (source=="Nullable<byte>") result="Integer";
if (source=="Nullable<sbyte>") result="Integer";
if (source=="Nullable<bool>") result="Integer";
if (source=="Nullable<boolean>") result="Integer";
if (source=="Nullable<Int16>") result="Integer";
if (source=="Nullable<short>") result="Integer";
if (source=="Nullable<Int32>") result="Integer";
if (source=="Int64") result="Long";
if (source=="long") result="Long";
if (source=="Long") result="Long";
if (source=="Nullable<Int64>") result="Long";
if (source=="Nullable<long>") result="Long";
if (source=="Nullable<Long>") result="Long";
if (source=="float") result="Double";
if (source=="Float") result="Double";
if (source=="decimal") result="Double";
if (source=="Decimal") result="Double";
if (source=="Nullable<float>") result="Double";
if (source=="Nullable<Float>") result="Double";
if (source=="Nullable<decimal>") result="Double";
if (source=="Nullable<Decimal>") result="Double";
if (source=="byte[]") result="byte[]";
if (source=="string") result="String";
if (source=="String") result="String";
if (source=="System.Date") result="String";
if (source=="System.Time") result="String";
if (source=="System.DateTime") result="String";
if (source=="Nullable<System.Date>") result="String";
if (source=="Nullable<System.Time>") result="String";
if (source=="Nullable<System.DateTime>") result="String";
return result;
}
#>
<#+
//Insert语句的第一段
string strInsertOneFormEntityProperty(EntityType entity)
{
string result="";
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
result+=","+edmProperty.Name;
}
return result.Substring(1);
}
#>
<#+
//Insert语句的第二段,特殊字段的默认值的问题,规律
string strInsert2(EntityType entity)
{
string result="";
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
//if ((edmProperty.Name=="create_time")||(edmProperty.Name=="update_time"))
string str=edmProperty.Name;
if (str.Contains("_time"))
{
result+=",now()";
}
else
{
result+=",#{"+getPropertyCamelName(edmProperty.Name)+"}";//edmProperty.Name;now()
}
}
return result.Substring(1);
}
#>