自己写的C#三层代码生成器

时间:2024-04-26 11:44:55
  • 思来想去用T4生成代码要学习它的语法,C#本身能很简单地生成txt文件,为啥不直接批量替换模板方式自己写个的三层代码生成器。说干就干,2个小时搞定。当然各层还可以做的更精细,比如DAL层Add方法Insert、Update语句中主键就不该出现等。但是大体上是能使用了。另外,生成的代码格式有些地方不规整,但是编译不出错,我们可以在实现具体类时借助vs格式化功能(快捷键ctrl+E+D)来使其规整或调模板。
  • 生成类文件整体思路:定模板,设置替换点,取得数据库中所有表及字段,遍历替换,输出cs文件。类文件模板是根据自己项目代码实践而定。
  • 具体算法:

    1、读取数据库中所有表及字段,返回DBInfo(Dictionary<{表,说明},Dictionary<{字段,说明},数据类型>>)

    2、遍历DBInfo,生成Model层代码

    3、遍历DBInfo,生成DAL层代码

    4、遍历DBInfo,生成BLL层代码
  • 代码说明:我是在现有旧项目中建的一个test.aspx中实现的,其中DbHelperSQL是数据库帮助类(网上可以随意找到),运行本代码前最好是先搭建的解决方案能访问DB了,再运行本代码,因为代码要连接项目DB,获得所有表及其字段以便批量生产三层文件。代码中用到的三层模板是我根据Dapper使用经验而确定的,大家可以替换成自己的。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Text;
using System.IO; public partial class test : System.Web.UI.Page
{
/***
* ○ 生成类文件整体思路:定模板,设置替换点,遍历DBInfo替换,输出cs文件。类文件模板是根据自己项目代码实践而定。
* ○ 具体算法:
* 1、读取数据库中所有表及字段,返回DBInfo(Dictionary<{表,说明},Dictionary<{字段,说明},数据类型>>)
* 2、遍历DBInfo,生成Model层代码
* 3、遍历DBInfo,生成DAL层代码
* 4、遍历DBInfo,生成BLL层代码
***/
protected void Page_Load(object sender, EventArgs e)
{
Dictionary<string, Dictionary<string, string>> r = GetDBInfo();
ModelFactory(r);
DALFactory(r);
BLLFactory(r);
Response.Write(r.Count);
}
#region 生成三层代码 #region 全局变量
static string DalNameSpace = "CMS.DAL";//DAL层命名空间(下同)
static string ModelNameSpace = "CMS.Model";
static string BllNameSpace = "CMS.BLL";
static string DalLayerPath = @"d:\Test\DAL\";//dal层代码生成代码文件存放路径(下同)
static string ModelLayerPath = @"d:\Test\Model\";
static string BllLayerPath = @"d:\Test\BLL\";
static char DicSplit = '≡';//分隔符,注意:代码不是因此出错,建议不要修改
#endregion #region 得到数据库中所有表及字段 private static Dictionary<string, Dictionary<string, string>> GetDBInfo()
{
//Dictionary<{表,说明},Dictionary<{字段,说明},数据类型>>
Dictionary<string, Dictionary<string, string>> dicR = new Dictionary<string, Dictionary<string, string>>();
string getTables = " SELECT name FROM sysobjects WHERE xtype = 'U' "; DataTable dt = DbHelperSQL.Query(getTables).Tables[0];
foreach (DataRow item in dt.Rows)
{
string tblName = item[0].ToString();
//"SELECT COLUMN_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + tblName+"' ";
string getTblFields = @"SELECT
表名 = case when a.colorder=1 then d.name else '' end,
表说明 = case when a.colorder=1 then isnull(f.value,'') else '' end,
字段序号 = a.colorder,
字段名 = a.name,
标识 = case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '√'else '' end,
主键 = case when exists(SELECT 1 FROM sysobjects where xtype='PK' and parent_obj=a.id and name in (
SELECT name FROM sysindexes WHERE indid in( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid))) then '√' else '' end,
类型 = b.name,
占用字节数 = a.length,
长度 = COLUMNPROPERTY(a.id,a.name,'PRECISION'),
小数位数 = isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),
允许空 = case when a.isnullable=1 then '√'else '' end,
默认值 = isnull(e.text,''),
字段说明 = isnull(g.[value],'')
FROM
syscolumns a
left join
systypes b
on
a.xusertype=b.xusertype
inner join
sysobjects d
on
a.id=d.id and d.xtype='U' and d.name<>'dtproperties'
left join
syscomments e
on
a.cdefault=e.id
left join
sys.extended_properties g
on
a.id=G.major_id and a.colid=g.minor_id
left join
sys.extended_properties f
on
d.id=f.major_id and f.minor_id=0
where d.name='" + tblName + "' order by a.id,a.colorder";
DataTable dtTbl = DbHelperSQL.Query(getTblFields).Tables[0];
Dictionary<string, string> dicItem = new Dictionary<string, string>();
foreach (DataRow tbl in dtTbl.Rows)
{
if (tbl[1].ToString() != "")
tblName += DicSplit + tbl[1].ToString();
string COLUMN_NAME = tbl[3].ToString() + DicSplit + tbl[12].ToString();
string DATA_TYPE = tbl[6].ToString();
dicItem.Add(COLUMN_NAME, DATA_TYPE);
}
dicR.Add(tblName, dicItem);
}
return dicR;
}
#endregion #region 遍历生成Model层代码
private static void ModelFactory(Dictionary<string, Dictionary<string, string>> dic)
{
foreach (var item in dic)
{
#region 类模板
StringBuilder sb = new StringBuilder();
sb.Append(" using System; \r\n");
sb.Append(" using System.Text; \r\n");
sb.Append(" \r\n");
sb.Append(" /************************************************** \r\n");
sb.Append(" * 类 名 称 : 【类名称】 \r\n");
sb.Append(" * 版 本 号 : v1.0.0.0 \r\n");
sb.Append(" * 说 明 : 【表职责】 \r\n");
sb.Append(" * 作 者 : \r\n");
sb.Append(" * 创建时间 : 【时间戳】 \r\n");
sb.Append(" **************************************************/ \r\n");
sb.Append(" namespace 【命名空间】 \r\n");
sb.Append(" { \r\n");
sb.Append(" public class 【表】 \r\n ");
sb.Append(" { \r\n");
sb.Append(" \r\n");
sb.Append(" public 【表】() \r\n");
sb.Append(" { \r\n ");
sb.Append(" } \r\n ");
sb.Append(" 【属性部分】 \r\n ");
sb.Append(" } \r\n ");
sb.Append(" } \r\n "); #endregion #region 属性部分
StringBuilder propPart = new StringBuilder();
foreach (var field in item.Value)
{
string[] key = field.Key.Split(DicSplit);
string type = ChangeToCSharpType(field.Value.ToString());//Dictionary<{表,说明},Dictionary<{字段,说明},数据类型>>
string fName = key[0];
string fRemark = key.Length == 2 ? key[1] : "";
string first = field.Key.Substring(0, 1);//第一个字母
fName = fName.Substring(1, fName.Length - 1);//不含第一个字母
string _f = first.ToLower() + fName;
string pF = first.ToUpper() + fName;
propPart.Append(" \r\n");
propPart.AppendFormat(" private {0} {1}; \r\n", type, _f);
propPart.AppendFormat(" //{0} \r\n", fRemark);
propPart.AppendFormat(" public {0} {1} \r\n", type, pF);
propPart.Append(" { \r\n");
propPart.Append(" get { return " + _f + "; } \r\n");
propPart.Append(" set { " + _f + " = value; } \r\n");
propPart.Append(" } \r\n");
}
#endregion string[] tableInfo = item.Key.Split(DicSplit);
string tblName = tableInfo[0];
string tblWork = tableInfo.Length == 2 ? tableInfo[1] : "";
string r = sb.ToString()
.Replace("【类名称】", tblName + "表实体类")
.Replace("【时间戳】", DateTime.Now.ToString())
.Replace("【命名空间】", ModelNameSpace)
.Replace("【表】", tblName)
.Replace("【表职责】", tblWork)
.Replace("【属性部分】", propPart.ToString());
CreateTxt(ModelLayerPath + tblName + "Model.cs", ModelLayerPath, r);
} }
#endregion #region 遍历生成DAL层代码
private static void DALFactory(Dictionary<string, Dictionary<string, string>> dic)
{ foreach (var item in dic)
{
StringBuilder sb = new StringBuilder();
#region 类模板
sb.Append("using System.Collections.Generic; \r\n");
sb.Append("using System.Text; \r\n ");
sb.Append(" \r\n ");
sb.Append("/************************************************** \r\n ");
sb.Append(" * 类 名 称 : 【类名称】 \r\n ");
sb.Append(" * 版 本 号 : v1.0.0.0 \r\n ");
sb.Append(" * 说 明 : 用于【表】数据持久化 \r\n ");
sb.Append(" * 作 者 : \r\n ");
sb.Append(" * 创建时间 : 【时间戳】 \r\n");
sb.Append("****************************************************/ \r\n ");
sb.Append("namespace 【命名空间】 \r\n ");
sb.Append("{ \r\n ");
sb.Append(" public class 【表】DAL \r\n ");
sb.Append(" { \r\n ");
sb.Append(" #region select \r\n ");
sb.Append(" \r\n ");
sb.Append(" public List<【表】> Select(【表】 model) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" string sql = \"SELECT * FROM 【表】 where \"; \r\n ");
sb.Append(" return DapperHelper.Select<【表】>(sql, model); \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" \r\n ");
sb.Append(" #region delete \r\n ");
sb.Append(" public bool Delete(【表】 model) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" string sql = \"DELETE FROM 【表】 WHERE Id=@Id\"; \r\n");
sb.Append(" return DapperHelper.NoQuery<【表】>(sql, model) > 0; \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" \r\n ");
sb.Append(" #region insert \r\n ");
sb.Append(" public bool Add(【表】 model) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" 【当前表Insert】 \r\n ");
sb.Append(" return DapperHelper.NoQuery<【表】>(sql.ToString(), model) > 0; \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" \r\n ");
sb.Append(" #region update \r\n ");
sb.Append(" public bool Update(【表】 model) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" 【当前表Update】 \r\n ");
sb.Append(" return DapperHelper.NoQuery<【表】>(sql, model) > 0; \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" } \r\n ");
sb.Append("} \r\n ");
#endregion
string tblName = item.Key.Split(DicSplit)[0];
string insetSQL = GetInsertSQL(tblName, item.Value);
string updateSQL = GetUpdateSQL(tblName, item.Value);
string r = sb.ToString()
.Replace("【类名称】", tblName + "表DAL类")
.Replace("【时间戳】", DateTime.Now.ToString())
.Replace("【命名空间】", DalNameSpace)
.Replace("【表】", tblName)
.Replace("【当前表Insert】", insetSQL)
.Replace("【当前表Update】", updateSQL);
CreateTxt(DalLayerPath + tblName + "DAL.cs", DalLayerPath, r);
} }
#endregion #region 遍历生成BLL层代码
private static void BLLFactory(Dictionary<string, Dictionary<string, string>> dic)
{ foreach (var item in dic)
{
StringBuilder sb = new StringBuilder();
#region 类模板
sb.Append("using System; \r\n");
sb.Append("using System.Collections.Generic; \r\n");
sb.Append("using System.Linq; \r\n");
sb.Append("using System.Text; \r\n");
sb.Append("using System.Threading.Tasks; \r\n");
sb.Append(" \r\n ");
sb.Append("/************************************************** \r\n ");
sb.Append(" * 类 名 称 : 【类名称】 \r\n ");
sb.Append(" * 版 本 号 : v1.0.0.0 \r\n ");
sb.Append(" * 说 明 : 用于【表】表业务操作 \r\n ");
sb.Append(" * 作 者 : \r\n ");
sb.Append(" * 创建时间 : 【时间戳】 \r\n");
sb.Append("****************************************************/ \r\n ");
sb.Append("namespace 【命名空间】 \r\n ");
sb.Append("{ \r\n ");
sb.Append(" public class 【表】BLL \r\n ");
sb.Append(" { \r\n ");
sb.Append(" #region select \r\n ");
sb.Append(" \r\n ");
sb.Append(" public List<【表】> Select(【表】 model, string sqlWhere) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" return 【表】DAL.Select(model, sqlWhere); \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" \r\n ");
sb.Append(" #region delete \r\n ");
sb.Append(" public bool Delete(【表】 model) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" return 【表】DAL.Delete(model); \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" \r\n ");
sb.Append(" #region insert \r\n ");
sb.Append(" public bool Add(【表】 model) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" return 【表】DAL.Add(model); \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" \r\n ");
sb.Append(" #region update \r\n ");
sb.Append(" public bool Update(【表】 model) \r\n ");
sb.Append(" { \r\n ");
sb.Append(" return 【表】DAL.Update(model); \r\n ");
sb.Append(" } \r\n ");
sb.Append(" #endregion \r\n ");
sb.Append(" } \r\n ");
sb.Append("} \r\n ");
#endregion
string tblName = item.Key.Split(DicSplit)[0];
string r = sb.ToString()
.Replace("【类名称】", tblName + "表BLL类")
.Replace("【时间戳】", DateTime.Now.ToString())
.Replace("【命名空间】", BllNameSpace)
.Replace("【表】", tblName);
CreateTxt(BllLayerPath + tblName + "BLL.cs", BllLayerPath, r);
} }
#endregion #region 其他 //为某个表生成insert语句
public static string GetInsertSQL(string tableName, Dictionary<string, string> filedDic)
{
StringBuilder sb = new StringBuilder(); sb.AppendFormat("StringBuilder sql = new StringBuilder(); \r\n");
sb.AppendFormat(" #region sql \r\n");
sb.AppendFormat(" sql.Append(\"INSERT INTO {0} \"); \r\n", tableName);
sb.AppendFormat(" sql.Append(\" ( \"); \r\n");
int i = 0;
foreach (var item in filedDic)
{
string[] key = item.Key.Split(DicSplit);
string filedName = key[0];
string splitChar = ",";
if (i + 1 == filedDic.Count)
splitChar = "";
sb.AppendFormat(" sql.Append(\" {0} {1} \"); \r\n", filedName, splitChar);
i++;
}
sb.AppendFormat(" sql.Append(\" ) \"); \r\n");
sb.AppendFormat(" sql.Append(\" VALUES ( \"); \r\n");
int b = 0;
foreach (var item in filedDic)
{
string[] key = item.Key.Split(DicSplit);
string filedName = key[0];
string splitChar = ",";
if (b + 1 == filedDic.Count)
splitChar = "";
sb.AppendFormat(" sql.Append(\" @{0} {1} \"); \r\n", filedName, splitChar);
b++;
}
sb.AppendFormat(" sql.Append(\" ) \"); \r\n");
sb.AppendFormat(" #endregion sql \r\n");
return sb.ToString();
} //为某个表生成update语句
public static string GetUpdateSQL(string tableName, Dictionary<string, string> filedDic)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("StringBuilder sql = new StringBuilder(); \r\n");
sb.AppendFormat(" #region sql \r\n");
sb.AppendFormat(" sql.Append(\" Update {0} set \"); \r\n", tableName);
int i = 0;
foreach (var item in filedDic)
{
string[] key = item.Key.Split(DicSplit);
string filedName = key[0];
string splitChar = ",";
if (i + 1 == filedDic.Count)
splitChar = "";
sb.AppendFormat(" sql.Append(\" {0}=@{0} {1} \"); \r\n", filedName, splitChar);
i++;
}
sb.AppendFormat(" sql.Append(\" Where Id=@Id \"); \r\n");
sb.AppendFormat(" #endregion sql \r\n");
return sb.ToString();
} //生成cs文件
public static void CreateTxt(string filePath, string folderPath, string fileContent)
{
if (!Directory.Exists(folderPath))//如果不存在就创建文件夹
Directory.CreateDirectory(folderPath);
FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.None);
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8);
sw.Write(fileContent);
sw.Close();
fs.Close();
} // 数据库中与C#中的数据类型对照
private static string ChangeToCSharpType(string type)
{
string reval = string.Empty;
switch (type.ToLower())
{
case "int":
reval = "int";
break;
case "text":
reval = "string";
break;
case "bigint":
reval = "int";
break;
case "binary":
reval = "byte[]";
break;
case "bit":
reval = "bool";
break;
case "char":
reval = "string";
break;
case "datetime":
reval = "DateTime";
break;
case "decimal":
reval = "decimal";
break;
case "float":
reval = "double";
break;
case "image":
reval = "byte[]";
break;
case "money":
reval = "decimal";
break;
case "nchar":
reval = "string";
break;
case "ntext":
reval = "string";
break;
case "numeric":
reval = "decimal";
break;
case "nvarchar":
reval = "string";
break;
case "real":
reval = "single";
break;
case "smalldatetime":
reval = "DateTime";
break;
case "smallint":
reval = "int";
break;
case "smallmoney":
reval = "decimal";
break;
case "timestamp":
reval = "DateTime";
break;
case "tinyint":
reval = "byte";
break;
case "uniqueidentifier":
reval = "System.Guid";
break;
case "varbinary":
reval = "byte[]";
break;
case "varchar":
reval = "string";
break;
case "Variant":
reval = "Object";
break;
default:
reval = "string";
break;
}
return reval;
}
#endregion #endregion
}

相关文章