• 思来想去用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. uboot中往s5p6818的emmc刷写内容

    建立分区: fdisk :: : fdisk Partition Map -- Partition Type: DOS Part Start Sector Num Sectors UUID Type ...

  2. 递归----Python

    #递归不仅仅是学习python中会遇到的一些问题,在学习每一个语言的过程中都会遇到递归.使用递归可以让复杂的循环变得简单. 递归:程序调用自身的行为 1.写一个数的阶乘 #递归 def factor( ...

  3. HTML table表格转换为Markdown table表格[转]

    举个栗子,当我想要把这个页面的第一个表格转换成Markdown Table时,怎么做更快,效率更高? 只需简单三步,请看示例: 第一步:复制包含HTML table标签的代码 复制table代码(HT ...

  4. 使用 navicat 导入导出数据库

    1.使用 navicat 导出数据库 2.使用 navicat 导入数据库导入之前需要先建好数据库 3.可以直接使用navicat 到数据传输功能直接将一个数库copy到另一个数据库

  5. js递归算法1+ 2+3.....100的和

    function num(n){    if(n==1) return 1;    return num(n-1)+n;}num(100);

  6. python的标准数据类型

    python有5种标准的数据类型 1. number(数字) int(有符号的整形) long(长整[也可以代表八进制和16进制]) float(浮点型) complex(复数类型) 2.string ...

  7. pytest自动化3:fixture之conftest.py实现setup

    出处:https://www.cnblogs.com/yoyoketang/p/9390073.html 前言: 前面一篇讲到用例加setup和teardown可以实现在测试用例之前或之后加入一些操作 ...

  8. git bash + gitee

    使用Git Bash从Gitee上下载代码到本地以及上传代码到码云Git: https://www.cnblogs.com/babysbreath/p/7274195.html 指定克隆远端分支 ht ...

  9. Wisdom RESTClient 使用教程

    Wisdom RESTClient 一款自动化测试REST API的工具,它可以自动化测试RESTful API并生成精美的测试报告,同时基于测试过的历史API,可以生成精美的RESTful API文 ...

  10. java ftp上传文件 工具类

    package com.learning.spboot.utils; import com.jcraft.jsch.*; import org.apache.commons.net.ftp.FTPCl ...