• 思来想去用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
}

自己写的C#三层代码生成器的更多相关文章

  1. 分享最近抽空写的一个代码生成器,集成EasyDBUtility数据库访问帮助类

    一直想写一个自己的代码生成器,但是因为工作事情多,一直搁置下来,最近下决心终于利用下班时间写完了,现在分享给有需要的朋友,代码生成器集成EasyDBUtility数据库访问帮助类,暂时只支持sqlse ...

  2. 使用 Node.js 写一个代码生成器

    背景 第一次接触代码生成器用的是动软代码生成器,数据库设计好之后,一键生成后端 curd代码.之后也用过 CodeSmith , T4.目前市面上也有很多优秀的代码生成器,而且大部分都提供可视化界面操 ...

  3. MVC+EF+Spring.Net代码生成器

    最近研究学习了MVC.EF等相关技术,写了一套项目架构.只要更改EF模型,生成数据库并转换T4模版.数据层和业务层就可以自动生成了. 主要用到的技术: 1.EF实体框架. 2.Spring.Net依赖 ...

  4. Rafy 领域实体框架示例(1) - 转换传统三层应用程序

    Rafy 领域实体框架发布后,虽然有帮助文档,许多朋友还是反映学习起来比较复杂,希望能开发一个示例程序,展示如何使用 Rafy 领域实体框架所以,本文通过使用 Rafy 领域实体框架来改造一个传统的三 ...

  5. 所有的代码生成器都是浮云,如果可以用aspx文件作为模板

    首先申明:标题中的如果是可以去掉的. 想写这篇文章很长时间了,一来是跟大家分享一下,别浪费时间在写代码生成器上面了,什么CodeSmith,XXCodeGenerator等等,都是浮云:二来想跟大家交 ...

  6. 简单的web三层架构系统【第五版】

    接上一版,今天差不多就是三层架构后台代码的完结了,这一版写完,接下来就是前台的制作了,前台不太熟悉,还在深入学习.过一段时间在写,今天先把后台代码写完. 三层架构包括DAL层, BLL层, UI层(也 ...

  7. 简单的web三层架构系统【第二版】

    昨天写了 web三层架构的第一版,准确的说是三层架构的前期,顶多算是个二层架构,要慢慢完善. 第一版里,程序虽说能运行起来,但是有一个缺陷,就是里面的SQL语句,是使用的拼接字符进行执行.这样安全系数 ...

  8. .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现

    本篇我将带着大家一起来对Dapper进行下封装并实现基本的增删改查.分页操作的同步异步方法的实现(已实现MSSQL,MySql,PgSQL).同时我们再实现一下仓储层的代码生成器,这样的话,我们只需要 ...

  9. MVC MVVM和传统三层的理解

    才学疏浅,请勿喷,如果有理解不对的地方请留言 其实,每个小小的程序员都有个毛病,就是反复写一个东西会觉得这个东西没有新意. 就像让你写三层,你却还是觉得想写MVC模式. 软件小公司做B/S的大部分还是 ...

随机推荐

  1. 开通blog,记录学习历程

    2017.12.15日,开通blog,用于回忆知识点的记录和整理. 开通本blog主要做以下几点事情: 1.巩固知识点,基础打牢: 2.在基础牢固的基础上,学习流行的框架: 3.在框架牢固的基础上学习 ...

  2. spring 定时任务执行2次

    eclipse 上定时任务执行没有问题,生产环境可以看到定时任务同时执行了2次,排除代码原因,网上找了些资料,最后发现是tomcat的原因, Host 节点中有一个appBase 属性指向了webap ...

  3. C#异常:未将对象引用设置到对象的实例。

    异常:未将对象引用设置到对象的实例. 一般是定义的变量或者数组等,没有赋初始值. 赋初始值后问题解决.

  4. shiro三连斩之第三斩,整合 springboot

    shiro爱springboot中使用 ,还有thymeleaf前端框架.主要是如何配置 pom.xml配置依赖 <?xml version="1.0" encoding=& ...

  5. angular4 富文本编辑器

    使用quill富文本编辑器实现,angular项目中用到了ngx-quill插件. quill的GitHub地址:https://github.com/quilljs/quill ngx-quill的 ...

  6. 在jsp里面 当鼠标元素触发onmouseover时,旁边出现一个浮动且跟随鼠标的div ,移开消失

    JSP页面 : <label onmouseover="showLongStrlog(window.event, '<list:seqnum></list:seqnu ...

  7. 自建 yum 源

    生产环境需要大规模的安装部署rpm包,每次安装,更新,都需要上传,安装,比较麻烦,可以在生产环境中自建一个yum源. 1.http安装 yum -y install httpd systemctl s ...

  8. waitGroup的使用

    package main import ( "fmt" "sync" "time" ) func main() { var wg sync. ...

  9. react中Redux应用框架学习

    1. 最普通的react-redux 2.应用context的傻瓜组件和聪明组件的redux框架  3. 精简版react-redux,利用react-redux模块的redux(推荐)  4.多个模 ...

  10. mdadm语法

    mdadm命令详解及实验过程   一.概念 mdadm是multiple devices admin的简称,它是Linux下的一款标准的软件 RAID 管理工具,作者是Neil Brown 二.特点 ...