CodeSmith对数据库中表的操作
在与数据库进行交互时, 我们使用到了一个CodeSmith自带的组件SchemaExplorer,利用这个组件我们可以访问数据库的数据表、存储过程、视图等,并可以得到相应的数据类型、标识列、列的(字段)
名称等信息。
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
SchemaExplorer.TableSchema类:是CodeSmith中自带的一个类,它描述表的结构。
Name属性:表的名称
Columns属性:表中列的集合
ExtendedProperties属性:表中指定列的扩展信息
ForeignKeyColumns属性:表的一个外键列的集合
ForeignKeys属性:表的外键集合
HasPrimaryKey属性:返回表中是否存在主键
NonForeignKeyColumns属性:表中非外键列的集合
NonKeyColumns属性:表中非外键,非主键列的集合
NonPrimaryKeyColumns属性:表中非主键列的集合
PrimaryKey属性:表中的主键
表中指定列的扩展属性 (ExtendedProperties属性):
CS_IsIdentity:自增长列
CS_IsComputed :计算列
CS_IdentitySeed :自增长列的起始值
CS_IdentityIncrement :自增长列的步长
CS_Default :列的默认值
例如:SQL Server定义了一个扩展属性来标识表中的唯一标识字段,在模版中可以这样写:
Identity Field =<% foreach(ColumnSchema cs in SourceTable.Columns) {
if( ((bool)cs.ExtendedProperties["CS_IsIdentity"].Value) == true)
{
Response.Write(cs.Name);
}
}
%>
要访问数据库中表的信息首选需要在CodeSmith中创建数据库的链接,步骤如下:
1、点击Schema Explorer中的Manage Data Sours图标
2、点击“add”添加一个新链接
3、添加完毕后在Schema Explorer中会出现新建的数据源
下面利用CodeSmith根据数据库的结构来生成存储过程
第一步还是指明模板使用的语言和生成的目标语言。
<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL" Description="Generates a update stored procedure." %>
第二步要加载使用访问数据库的组件SchemaExplorer,并声明其使用的命名空间。
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
第三步定义一个存储表名称使用的变量,然后指明这个变量类型为SchemaExplorer.TableSchema,这样我们可以通过这个变量得到相应的表的信息。
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context" %>
第四步下面利用循环语句遍历表的各个列,拼出存储过程需要传递的参数,以列名作为参数名。
<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
<%= GetSqlParameterStatement(SourceTable.Columns[i]) %><% if (i < SourceTable.Columns.Count - 1) { %>,<% } %>
<% } %>
其中的GetSqlParameters是自定义的CodeSmith中的脚本函数,形参接收列对象,返回拼完的参数。
<script runat="template">
public string CreateParams(ColumnSchema column) //接收列对象
{
string strparams="@";
strparams += column.Name+" "+column.NativeType.ToString();//在列名前加@符号拼成参数名
switch(column.DataType) //根据列对象类型,为参数定义其类型及长度。
{
case DbType.Decimal:
{
strparams += "("+column.Precision.ToString()+","+column.Scale.ToString()+")";
break;
}
default:
{
strparams += "("+column.Size+")";
break;
}
}
return strparams;
}
</script>
第五步下面来生成需要更新的字段,更新时仅能更新非主键字段的值,在SchemaExplorer中支持这种区别,使用SourceTable.NonPrimaryKeyColumns即可得到非主键字段的集合。
UPDATE [<%= SourceTable.Name %>] SET
<% for (int i = 0; i < SourceTable.NonPrimaryKeyColumns.Count; i++) { %>
[<%= SourceTable.NonPrimaryKeyColumns[i].Name %>] = @<%= SourceTable.NonPrimaryKeyColumns[i].Name %><% if (i < SourceTable.NonPrimaryKeyColumns.Count - 1) { %>,<% } %>
<% } %>
第六步然后再使用SourceTable.PrimaryKey.MemberColumns得到数据表中的主键集合,生成更新条件
WHERE
<% for (int i = 0; i < SourceTable.PrimaryKey.MemberColumns.Count; i++) { %>
<% if (i > 0) { %>AND <% } %>
[<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>] = @<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>
<% } %>
生成表的添加存储过程
<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="" Inherits="" Debug="False" Description="Template description here." %>
<%@ Property Name="STable" Type="SchemaExplorer.TableSchema" Default="" Optional="False" Category="Context"%>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
create procedure UP_<%=STable.Name.ToUpper()%>_INSERT
<%for(int i=0;i<STable.Columns.Count;i++){%>
<%if((bool)STable.Columns[i].ExtendedProperties["CS_IsIdentity"].Value==true) continue;%><%--跳过自增长列--%>
<%=CreateParams(STable.Columns[i])%><%if(i<STable.Columns.Count-1){%>,<%}%>
<%}%>
as
insert into <%=STable.Name%> (<%for(int i=0;i<STable.Columns.Count;i++){%>
<%--跳过自增长列--%>
<%if((bool)STable.Columns[i].ExtendedProperties["CS_IsIdentity"].Value==true) continue;%>
<%--输出列名列表,如果多列用逗号隔开--%>
<%=STable.Columns[i].Name%><%if(i<STable.Columns.Count-1)%>,<%} %>)
values(<%for(int i=0;i<STable.Columns.Count;i++){%>
<%--跳过自增长列--%>
<%if((bool)STable.Columns[i].ExtendedProperties["CS_IsIdentity"].Value==true) continue;%>
<%--加上参数名(在列名前加@),如果有多个列值用逗号隔开--%>
@<%=STable.Columns[i].Name%><%if(i<STable.Columns.Count-1){%>,<%}%><%}%>)
go
<%--生成参数列表的CodeSmith脚本--%>
<script runat="template">
public string CreateParams(ColumnSchema column)
{
string strparams="@";
strparams += column.Name+" "+column.NativeType;
switch(column.DataType)
{
case DbType.Decimal:
{
strparams += "("+column.Precision+","+column.Scale+")";
break;
}
default:
{
strparams += "("+column.Size+")";
break;
}
}
return strparams;
}
</script>
CodeSmith的执行结果:
生成表的更新存储过程
<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="" Inherits="" Debug="False" Description="Generate a update stored procedure" %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Default="" Optional="False" Category="Context" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
create procedure UP_<%=SourceTable.Name.ToUpper()%>_UPDATE
<%for(int i=0;i<SourceTable.Columns.Count;i++){ if((bool)SourceTable.Columns[i].ExtendedProperties["CS_IsIdentity"].Value==true) continue;%>
<%=CreateParams(SourceTable.Columns[i])%><%if(i<SourceTable.Columns.Count-1){%>,<%}%>
<%}%>
as
update <%=SourceTable.Name%> set
<%for(int i=0;i<SourceTable.NonPrimaryKeyColumns.Count;i++){ if((bool)SourceTable.Columns[i].ExtendedProperties["CS_IsIdentity"].Value == true) continue;%>
<%=SourceTable.NonPrimaryKeyColumns[i].Name%>=@<%=SourceTable.NonPrimaryKeyColumns[i].Name%><%if(i<SourceTable.NonPrimaryKeyColumns.Count-1){%>,<%}%>
<%}%>
where
<%for(int i=0;i<SourceTable.PrimaryKey.MemberColumns.Count;i++){%>
<%if(i>0){ %> and <% }%>
<%=SourceTable.PrimaryKey.MemberColumns[i].Name%>=@<%=SourceTable.PrimaryKey.MemberColumns[i].Name%>
<%}%>
go
<script runat="template">
public string CreateParams(ColumnSchema column)
{
string strparams="@";
strparams += column.Name+" "+column.NativeType.ToString();
switch(column.DataType)
{
case DbType.Decimal:
{
strparams += "("+column.Precision.ToString()+","+column.Scale.ToString()+")";
break;
}
default:
{
strparams += "("+column.Size+")";
break;
}
}
return strparams;
}
</script>
CodeSmith的执行结果