完整教程鏈接:ASP.Net: EshineASPNet-基於ASP.Net敏捷開發開源框架
本教程介紹一套自主開發的項目實現自動生成代碼,以及使用codesmith自動生成代碼。
首先要講的是在一個項目裏面,很多代碼是有共性的,比如數據庫表要對應類,增刪改查的方法,這些都是公用的必須有的,做這個算沒有創意的體力活,堆代碼,這種就最適合用自動生成了。
然後是三層架構,這是一個比較老的話題了,也能搜到很多文章,因爲這裏用到了就提一下。數據庫每一個表對應一個Model,對這個Model的數據庫操作放進SQLServerDAL,接口提取到IDAL,最後就可以在上面封裝業務邏輯成Bll了,這裏也加了DALFactory這個用來預留個更換數據庫的可能。那麼一旦一個數據庫表定義好以後,這幾個類的代碼其實都是可以初始化生成一次的,最後只是在Bll裏面添加更多的函數就可以了。雖說老或者不好,也就是說有Linq更新的查詢方式,和主要用於Webform而不是MVC。不過數據庫執行效率是比Linq要高的,對sql的磨練是好的,對分層的理解是需要的。
本框架包含了一個Windows應用,在csswrap文件夾,用來實現根據數據表信息自動生成從Model到Bll的所有代碼並保存文件至對應文件夾。懶人有懶方法,直接假設表的第一個字段是自增id,設成主鍵和標識。右擊Sql Server數據庫的表-編輯表腳本爲(S)-CREAT到(C)-新建編輯器窗口,複製從CREATE TABLE行到字段最後一行(即CONSTRAINT的上面一行),例如
CREATE TABLE [dbo].[province](
[id] [int] IDENTITY(1,1) NOT NULL,
[code] [nvarchar](6) NULL,
[name] [nvarchar](40) NULL,
這裏就包含了表名,字段名和字段類型,我們根據這些信息自動生成對應的Model,DAL,Bll等。做到這一點其實就是用StringBuilder不斷Append就好了。
private void button2_Click(object sender, EventArgs e)
{
if(! getfolderpath()) return;
//[customerName] [varchar](50) NULL,
Regex r = new Regex(@"\[\w*\]");
Match mch = Regex.Match(this.richTextBox3.Lines[0], @"dbo\]\.\[(?<tname>\w+)\]");
string tname = mch.Groups["tname"].Value;//table name
mch = Regex.Match(this.richTextBox3.Lines[1], @"\[(?<idname>\w+)\]");
string idname=mch.Groups["idname"].Value;
string s1, s2;
StringBuilder sb1 = new StringBuilder();//model前部分
StringBuilder sb2 = new StringBuilder();//model後部分
StringBuilder sb3 = new StringBuilder();//sqlServerDal
StringBuilder sb4 = new StringBuilder();//sqlServerDal
StringBuilder sb5 = new StringBuilder();//sqlServerDal
StringBuilder sb6 = new StringBuilder();//sqlServerDal
StringBuilder sb7 = new StringBuilder();//interface
StringBuilder sb8 = new StringBuilder();//bll
StringBuilder sb9 = new StringBuilder();//sqlServerDal
StringBuilder sb10 = new StringBuilder();//DALFactory
sb1.Append("using System;\n\n");
sb1.Append("namespace Model\n{\n");
sb1.Append("public class " + tname + "\n{\n");
sb1.Append("private int _" + idname + " = 0;\n");
sb2.Append("public int " + idname + "{get { return _" + idname + "; }\n\tset { _" + idname + " = value; }}\n\n");
sb3.Append("using System;\n");
sb3.Append("using System.Text;\n");
sb3.Append("using System.Data;\n\n");
sb3.Append("namespace SQLServerDAL\n{\n");
sb3.Append("public class sql_" + tname + ":IDAL." + tname + "Dal\n{\n");
sb3.Append("DBunit.SQLAccess sql = new DBunit.SQLAccess();\n");
sb3.Append("DateTime baddate = DateTime.Parse(\"1900-01-01\");\n");
sb3.Append("public int Add(Model."+tname+" "+tname+")\n{\n");
sb3.Append("StringBuilder strsql = new StringBuilder();\n");
sb3.Append("strsql.Append(\"insert into " + tname + " values (\");\n");
sb4.Append("public Model." + tname + " get" + tname + "(DataTable dt)\n{\n");
sb4.Append("Model." + tname + " " + tname + " = new Model." + tname + "();\n");
sb4.Append(tname + "." + idname + " = int.Parse( dt.Rows[0][\"" + idname + "\"].ToString());\n");
sb7.Append("using System.Data;\n\n");
sb7.Append("namespace IDAL\n{\n");
sb7.Append("public interface " + tname + "Dal\n{\n");
sb7.Append("int Add(Model." + tname + " " + tname + ");\n");
sb8.Append("using System.Data;\n\n");
sb8.Append("namespace Bll\n{\n");
sb8.Append("public class " + tname + "Bll\n{\n");
sb8.Append("IDAL." + tname + "Dal itu = DALFactory." + tname + "_Factory.Createusers();\n");
sb8.Append("public int Add(Model." + tname + " " + tname + ")\n{\n");
sb8.Append("return itu.Add(" + tname + ");\n}\n");
sb9.Append("public Model." + tname + " get" + tname + "(int id)\n{\n");
sb9.Append("StringBuilder strsql = new StringBuilder();\n");
sb9.Append("strsql.Append(\"select * from " + tname + " where \");\n");
sb9.Append("strsql.AppendFormat(\"" + idname + "='{0}'\", id);\n");
sb9.Append("DataTable dt = sql.ExecuteDataSet(strsql.ToString()).Tables[0];\n");
sb9.Append("if (dt.Rows.Count < 1) return null;\n\n");
sb9.Append("return get" + tname + "(dt);\n}\n");
sb7.Append("Model." + tname + " get" + tname + "(int id);\n");
sb7.Append("Model." + tname + " get" + tname + "(DataTable dt);\n");
sb8.Append("public Model." + tname + " get" + tname + "(int id)\n{\n");
sb8.Append("return itu.get" + tname + "(id);\n}\n");
sb8.Append("public Model." + tname + " get" + tname + "(DataTable dt)\n{\n");
sb8.Append("return itu.get" + tname + "(dt);\n}\n");
sb5.Append("public int update(Model." + tname + " " + tname + ")\n{\n");
sb5.Append("StringBuilder strsql = new StringBuilder();\n");
sb5.Append("strsql.Append(\"update " + tname + " set \");\n");
sb7.Append("int update(Model." + tname + " " + tname + ");\n");
sb8.Append("public int update(Model." + tname + " " + tname + ")\n{\n");
sb8.Append("return itu.update(" + tname + ");\n}\n");
sb10.Append("using System.Reflection;\n\n");
sb10.Append("namespace DALFactory\n{\n");
sb10.Append("public class " + tname + "_Factory\n{\n");
sb10.Append("static readonly string path = System.Configuration.ConfigurationManager.AppSettings[\"DAL\"];\n");
sb10.Append("public static IDAL." + tname + "Dal Createusers()\n{\n");
sb10.Append("string classname = path + \".sql_" + tname + "\";\n");
sb10.Append("return (IDAL." + tname + "Dal)Assembly.Load(path).CreateInstance(classname);\n}\n");
sb10.Append("}\n}");
for (int i = 2; i < this.richTextBox3.Lines.Length; i++)//0行是表名,1行是id
{
if (this.richTextBox3.Lines[i].Contains("] ["))
{
s1 = r.Matches(this.richTextBox3.Lines[i])[0].ToString();
s1 = s1.Substring(1, s1.Length - 2);
s2 = r.Matches(this.richTextBox3.Lines[i])[1].ToString();
s2 = s2.Substring(1, s2.Length - 2);
switch (s2)
{
case "varchar": sb1.Append("private string _" + s1 + " = \"\";\n");
sb2.Append("public string " + s1 + "{get { return _" + s1 + "; }\n\tset { _" + s1 + " = value; }}\n\n");
sb3.Append("strsql.AppendFormat(\"'{0}',\", " + tname + "." + s1 + ");\n");
sb4.Append(tname + "." + s1 + " = dt.Rows[0][\"" + s1 + "\"].ToString();\n");
sb5.Append("strsql.AppendFormat(\" " + s1 + " ='{0}',\", " + tname + "." + s1 + ");\n");
break;
case "nvarchar": sb1.Append("private string _" + s1 + " = \"\";\n");
sb2.Append("public string " + s1 + "{get { return _" + s1 + "; }\n\tset { _" + s1 + " = value; }}\n\n");
sb3.Append("strsql.AppendFormat(\"N'{0}',\", " + tname + "." + s1 + ");\n");
sb4.Append(tname + "." + s1 + " = dt.Rows[0][\"" + s1 + "\"].ToString();\n");
sb5.Append("strsql.AppendFormat(\" " + s1 + " =N'{0}',\", " + tname + "." + s1 + ");\n");
break;
case "text": sb1.Append("private string _" + s1 + " = \"\";\n");
sb2.Append("public string " + s1 + "{get { return _" + s1 + "; }\n\tset { _" + s1 + " = value; }}\n\n");
sb3.Append("strsql.AppendFormat(\"'{0}',\", " + tname + "." + s1 + ");\n");
sb4.Append(tname + "." + s1 + " = dt.Rows[0][\"" + s1 + "\"].ToString();\n");
sb5.Append("strsql.AppendFormat(\" " + s1 + " ='{0}',\", " + tname + "." + s1 + ");\n");
break;
case "datetime": sb1.Append("private DateTime _" + s1 + "= DateTime.Parse(\"1900-01-01\");\n");
sb2.Append("public DateTime " + s1 + "{get { return _" + s1 + "; }\n\tset { _" + s1 + " = value; }}\n\n");
sb3.Append("strsql.AppendFormat(\"{0},\", " + tname + "." + s1 + " == baddate ? \"null\" :\"'\" + " + tname + "." + s1 + ".ToString() +\"'\");\n");
sb4.Append(tname + "." + s1 + " = dt.Rows[0][\"" + s1 + "\"].ToString() == \"\" ? baddate : DateTime.Parse(dt.Rows[0][\"" + s1 + "\"].ToString());\n");
sb5.Append("strsql.AppendFormat(\" " + s1 + " ={0},\", " + tname + "." + s1 + " == baddate ? \"null\" :\"'\" + " + tname + "." + s1 + ".ToString() +\"'\");\n");
break;
case "int": sb1.Append("private int _" + s1 + " = 0;\n");
sb2.Append("public int " + s1 + "{get { return _" + s1 + "; }\n\tset { _" + s1 + " = value; }}\n\n");
sb3.Append("strsql.AppendFormat(\"{0},\", " + tname + "." + s1 + ");\n");
sb4.Append(tname + "." + s1 + " = int.Parse( dt.Rows[0][\"" + s1 + "\"].ToString());\n");
sb5.Append("strsql.AppendFormat(\" " + s1 + " ='{0}',\", " + tname + "." + s1 + ");\n");
break;
case "decimal": sb1.Append("private decimal _" + s1 + " = 0M;\n");
sb2.Append("public decimal " + s1 + "{get { return _" + s1 + "; }\n\tset { _" + s1 + " = value; }}\n\n");
sb3.Append("strsql.AppendFormat(\"{0},\", " + tname + "." + s1 + ");\n");
sb4.Append(tname + "." + s1 + " = decimal.Parse( dt.Rows[0][\"" + s1 + "\"].ToString());\n");
sb5.Append("strsql.AppendFormat(\" " + s1 + " ='{0}',\", " + tname + "." + s1 + ");\n");
break;
case "float": sb1.Append("private double _" + s1 + " = 0.0;\n");
sb2.Append("public double " + s1 + "{get { return _" + s1 + "; }\n\tset { _" + s1 + " = value; }}\n\n");
sb3.Append("strsql.AppendFormat(\"{0},\", " + tname + "." + s1 + ");\n");
sb4.Append(tname + "." + s1 + " = double.Parse( dt.Rows[0][\"" + s1 + "\"].ToString());\n");
sb5.Append("strsql.AppendFormat(\" " + s1 + " ='{0}',\", " + tname + "." + s1 + ");\n");
break;
default: sb1.Append("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
sb2.Append("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
break;
}
}
}
sb2.Append("}\n}");
sb3.Remove(sb3.ToString().LastIndexOf(",\",") , 1);
sb3.Append("strsql.Append(\") select SCOPE_IDENTITY()\");\n");
sb3.Append("return Convert.ToInt32(sql.ExecuteSc(strsql.ToString()));\n}\n");
sb4.Append("return " + tname + ";\n}\n");
sb5.Remove(sb5.ToString().LastIndexOf(",\","), 1);
sb5.Append("strsql.AppendFormat(\" where " + idname + "={0}\", " + tname + "." + idname + ");\n");
sb5.Append("return sql.ExecuteNonQuery(strsql.ToString());\n}\n");
sb6.Append("public int Delete(int " + idname + ")\n{\n");
sb6.Append("return sql.ExecuteNonQuery(\"delete from " + tname + " where " + idname + "=\" + " + idname + ");\n}\n");
sb6.Append("public DataTable Select(string ss)\n{\n");
sb6.Append("return sql.ExecuteDataSet(ss).Tables[0];\n}\n");
sb7.Append("int Delete(int " + idname + ");\n");
sb7.Append("DataTable Select(string ss);\n");
sb7.Append("}\n}");
sb8.Append("public int Delete(int " + idname + ")\n{\n");
sb8.Append("return itu.Delete(" + idname + ");\n}\n");
sb8.Append("public DataTable Select(string ss)\n{\n");
sb8.Append("return itu.Select(ss);\n}\n}\n}");
sb6.Append("}\n}");
this.richTextBox4.Text = sb1.ToString() + "\n\n" + sb2.ToString();//model
this.richTextBox7.Text = sb3.ToString() + "\n\n" + sb4.ToString() + "\n\n" + sb9.ToString() + "\n\n" + sb5.ToString() + "\n\n" + sb6.ToString();//sqlserverdal
this.richTextBox8.Text = sb7.ToString();//idal
this.richTextBox9.Text = sb8.ToString();//bll
this.richTextBox14.Text = sb10.ToString();//dalfactory
string filepath = folderpath + "\\Bll\\" + tname + "Bll.cs";
if (File.Exists(filepath))
{
FileInfo fileInfo = new FileInfo(filepath);
fileInfo.MoveTo(folderpath + "\\Bll\\" + tname + "Bll"+DateTime.Now.ToString("yyyyMMddHHmmss") +".cs");
}
File.AppendAllText(filepath, this.richTextBox9.Text.Replace("\n", "\r\n"), Encoding.Default);
filepath = folderpath + "\\Model\\" + tname + ".cs";
if (File.Exists(filepath)) File.Delete(filepath);
File.AppendAllText(filepath, this.richTextBox4.Text.Replace("\n", "\r\n"), Encoding.Default);
filepath = folderpath + "\\SQLServerDAL\\sql_" + tname + ".cs";
if (File.Exists(filepath)) File.Delete(filepath);
File.AppendAllText(filepath, this.richTextBox7.Text.Replace("\n", "\r\n"), Encoding.Default);
filepath = folderpath + "\\IDAL\\" + tname + "Dal.cs";
if (File.Exists(filepath)) File.Delete(filepath);
File.AppendAllText(filepath, this.richTextBox8.Text.Replace("\n", "\r\n"), Encoding.Default);
filepath = folderpath + "\\DALFactory\\" + tname + "_Factory.cs";
if (File.Exists(filepath)) File.Delete(filepath);
File.AppendAllText(filepath, this.richTextBox14.Text.Replace("\n", "\r\n"), Encoding.Default);
}
就是這麼長段的Append最終得到了我們需要的文件,最後在每個項目裏面添加現有項就可以使用了。這是Windows應用所以要去Debug文件夾運行這個exe程序。
除了自己寫,也可以使用工具,比如CodeSmith,這裏給一個生成Entity的樣例,選擇數據庫的表以後就會執行並生成文件。
<%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" ResponseEncoding="UTF-8" Inherits="" Debug="False" Description="Template description here." %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context" Description="Table that the object is based on." %>
<%--@ Property Name="ModuleName" Type="System.String" Optional="false" Category="Context" --%>
<%@ Property Name="package" Type="System.String" Optional="false" Category="Context" Default="com.test"%>
<%@ Property Name="className" Type="System.String" Optional="false" Category="Context" Default="Test"%>
<%--@ Property Name="SourceDatabase" type="SchemaExplorer.DatabaseSchema" DeepLoad="True" Optional="False" Category="01. GettingStarted - Required" Description="Database that the tables views, and storedprocedures should be based on. IMPORTANT!!! If SourceTables and SourceViews areleft blank, the Entire Database will then be generated."--%>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="System.Data" %>
<%@ Assembly Name="CodeSmith.CustomProperties" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="CodeSmith.CustomProperties" %>
<%@ Import Namespace="System.Windows.Forms.Design" %>
<%@ Import Namespace="System.IO" %>
<script runat="template">
public string modelPackage = "entity1";
public string getColumnName(string columnName, Boolean isClass){
if(columnName == null || columnName.Equals("")){
return "";
}
int indx = columnName.IndexOf("_");
if(indx != -1){
columnName = columnName.ToLower();
string[] names = columnName.Split('_');
columnName = "";
for(int i=0;i<names.Length;i++){
if(i==0 && !isClass){
columnName += names[i].Substring(0,1).ToLower();
}else{
columnName += names[i].Substring(0,1).ToUpper();
}
columnName += names[i].Substring(1,names[i].Length - 1);
}
} else {
if(isClass){
columnName = columnName.Substring(0,1).ToUpper() + columnName.Substring(1,columnName.Length - 1);
} else {
columnName = columnName.Substring(0,1).ToLower() + columnName.Substring(1,columnName.Length - 1);
}
}
return columnName;
}
public string getTypeName(ColumnSchema column){
return column.NativeType.ToUpper();
}
public string getColumnType(ColumnSchema column){
switch (getTypeName(column)){
case "BIGINT": return "Long";
case "IMAGE":
case "REAL":
case "VARBINARY":
case "SQL_VARIANT":
case "BLOB":
case "CLOB":
case "BINARY": return "Byte[]";
case "BIT":
case "SMALLINT":
case "TINYINT": return "int";
case "FLOAT": return "float";
case "NUMBER":
case "INT": return "int";
case "DECIMAL":
case "NUMERIC":
case "MONEY": return "decimal";
case "NCHAR":
case "NTEXT":
case "NVARCHAR": return "string";
case "DATE":
case "DATETIME":
case "SMALLDATETIME": return "DateTime";
case "SMALLMONEY": return "decimal";
case "VARCHAR":
case "VARCHAR2":
case "SYSNAME":
case "CHAR":
case "TEXT": return "String";
default: return getTypeName(column);
}
}
public string getClassName(TableSchema table){
return table.Name.Replace("db_", "DB")
.Replace("rel_", "Rel")
.Replace("biz_", "Biz")
.Replace("log_", "Log")
.Replace("sys_", "Sys");
}
public string path = "d:\\test";
public string fileName = "test.txt";
public void CreateDirectory(string path){
if(!Directory.Exists(path)){
Directory.CreateDirectory(path);
} else {
//Directory.Delete(path,true);
Directory.CreateDirectory(path);
}
}
public override void Render(TextWriter tw)
{
CreateDirectory(path);
//base.Render(tw);
StreamWriter fs2 = new StreamWriter(path + "\\" + fileName,true);
this.Response.AddTextWriter(fs2);
base.Render(tw);
fs2.Close();
}
</script>
using System;
using FluentNHibernate.Mapping;
namespace <%=this.package%>.Framework.Model.Mapping
{
public class <%=getClassName(this.SourceTable)%>Map : ClassMap<<%=getClassName(this.SourceTable)%>>
{
public <%=getClassName(this.SourceTable)%>Map()
{
Table("<%=this.SourceTable%>");
Id(x => x.Id).Column("<%=getColumnName(this.SourceTable.Columns[0].Name,false) %>").GeneratedBy.Identity();
Map(x => x.CreateTime);
Map(x => x.UpdateTime);
Map(x => x.IsShow);
Map(x => x.IsDel);
<%
bool firstone=true;
foreach(ColumnSchema col in this.SourceTable.Columns)
{
string columnName = col.Name;
if(columnName != "IsDel" && columnName != "IsShow" && columnName != "CreateTime" && columnName != "UpdateTime")
{
if(firstone) {firstone=false; continue; }
%>
Map(x => x.<%=getColumnName(columnName,false) %>).Column("<%=columnName %>");
<%
}
}%>
}
}
}
本教程代碼參考 EshineASPNet\csswrap\main.cs