• 思来想去用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. SVN分支与合并【超详细的图文教程】(转载)

    SVN分支与合并 一. 分支与合并的概念 二. SVN分支的意义 三. 如何创建分支与合并分支 一.分支与合并的概念: 分支:版本控制系统的一个特性是能够把各种修改分离出来放在开发品的一个分割线上.这 ...

  2. Python知识体系思维导图:

    基础知识 数据类型 1.序列 2.字符串 3.列表和元组 4.字典和集合 循环 & 判断

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

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

  4. Python基础学习---位运算符

    <<   左移,每移动1位,相当于乘以2      例如:32<<2    等价于:32*4 ==128 >>   右移,每移动1位,相当于除以2      例如: ...

  5. KendoUi 学习笔记一

    本系列主要是记录KendoUI的学习过程. KendoUi的特点有以下特点: 1. 70+UI控件 控件有DataGrids,DropDowns,Menus和Buttons,还有一些商业的控件,比如C ...

  6. jmeter下载和配置

    一.下载 1.进入官网:http://jmeter.apache.org/ 3.环境变量相关配置 电脑桌面---->“计算机”图标---->鼠标右键选择“属性”---->点击高级系统 ...

  7. background属性冲突导致的部分浏览器背景图片不显示问题

    前几天在项目中遇到了一个让人摸不着头脑的bug,测试说页面显示有点问题并发了截图, 正常的显示状态是这样 首先我自信地用自己的手机检查了一下,没有问题,问清楚后得知是UC浏览器中出现的,UC的内核是u ...

  8. oracle针对某列让特定信息排序[decode]

    在ORACLE查询中,如果在没有排序,但又想让某列中特定值的信息排到前面的时候,使用oracle的decode(字段,'字段值',数字) 如 select name from user 查询出来的所有 ...

  9. silverlight 控件样式动态绑定

    <telerik:RadDiagram x:Name="diagram1" GraphSource="{Binding GraphSource, Mode=TwoW ...

  10. SpringBoot的启动流程分析(1)

    通过分析我们可以找到 org.springframework.boot.SpringApplication 中如下, public static ConfigurableApplicationCont ...