简单代码生成器原理剖析(二)

简介:

上篇《简单代码生成器原理剖析(一)》分析了代码生成器的原理,查询数据库系统视图:INFORMATION_SCHEMA.TABLES、 INFORMATION_SCHEMA.COLUMNS  可以获得数据库中表、列的相关信息,再运用StringBuilder类的其AppendLine方法追加字符串,最后早运用File.WriteAllText方法将字符串写入文件。

第二版代码生成器在第一版的基础上扩展了以下功能:

  • 使用了部分类(partial):当使用大项目或自动生成的代码(如由 Windows 窗体设计器提供的代码)时,将一个类、结构或接口类型拆分到多个文件中的做法就很有用。 分部类型可能包含分部方法。
  •  使用可空类型:由于数据库中表中数据很有可能是NULL,可空类型使得数据从表中读取出来赋值给值类型更加兼容。
  • 增加了ToModel方法:将数据库表中一行数据封装成Model类的对象返回。
 
Model的实现:
复制代码
        /// <summary>
/// Model
/// </summary>
public static void CreateModel(CodeBuilderArgs args,string tableName)
{
DataTable dt = ExecuteDataTable(args.ConnectionString, "select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=@TABLE_NAME"
,new SqlParameter("TABLE_NAME",tableName));
StringBuilder sb = new StringBuilder();
sb.AppendLine("using System;");
sb.AppendLine("using System.Collections.Generic;");
sb.AppendLine("using System.Linq;");
sb.AppendLine("using System.Text;");
sb.AppendLine("namespace " + args .Namespace+ ".Model");
sb.AppendLine("{");
sb.AppendLine("partial class " + tableName);
sb.AppendLine("{");
foreach (DataRow row in dt.Rows)
{
string colName = Convert.ToString(row["COLUMN_NAME"]);
string colType = Convert.ToString(row["DATA_TYPE"]);

Type netType = GetTypeByDBType(colType);
string netTypeName;
if (netType.IsValueType)
{
netTypeName = netType + "?";
}
else
{
netTypeName = netType.ToString();
}
sb.AppendLine("public " +netTypeName +" "+ colName + " { get; set; }");
}
sb.AppendLine(" }");
sb.AppendLine(" }");
string modelDir = Path.Combine(args.OutputDir, "Model");
string modelFile = Path.Combine(modelDir, tableName+".cs");
Directory.CreateDirectory(modelDir);
File.WriteAllText(modelFile, sb.ToString());
}
复制代码
DAL(数据访问层)的实现:
 
复制代码
        /// <summary>
///DAL
/// </summary>
/// <param name="args"></param>
/// <param name="tableName"></param>
public static void CreateDAL(CodeBuilderArgs args, string tableName)
{
StringBuilder sb = new StringBuilder();
DataTable dt = ExecuteDataTable(args.ConnectionString, "select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=@TABLE_NAME"
, new SqlParameter("TABLE_NAME", tableName));
sb.AppendLine("using System;");
sb.AppendLine("using System.Collections.Generic;");
sb.AppendLine("using System.Linq;");
sb.AppendLine("using System.Text;");
sb.AppendLine("using "+args.Namespace+".Model;");
sb.AppendLine("using System.Data.SqlClient;");
sb.AppendLine("using System.Data;");
sb.AppendLine("namespace "+args.Namespace+".DAL");
sb.AppendLine("{");
sb.AppendLine("partial class "+tableName+"DAL");
sb.AppendLine("{");
sb.AppendLine("public int AddNew("+tableName+" model)");
sb.AppendLine("{");

string[] cols = GetColsWithoutId(GetCols(dt, new List<string>())).ToArray();
var colsParameters=from e in cols select"@"+ e;
sb.AppendLine("string sql = \"insert into " + tableName + "(" + string.Join(",", cols) + ") output inserted.id values(" + string.Join(",", colsParameters.ToArray()) + ")\";");
sb.AppendLine("int id = (int)SqlHelper.ExecuteScalar(sql");

foreach (DataRow row in dt.Rows)
{
string colName = Convert.ToString(row["COLUMN_NAME"]);
if(!(colName.ToLower()=="id"))
{
sb.AppendLine(", new SqlParameter(\""+colName+"\", model."+colName+")");
}

}
sb.AppendLine(");");
sb.AppendLine("return id;");
sb.AppendLine("}");

var par=from e in cols select e+"="+"@"+e;
sb.AppendLine("public bool Update("+tableName+" model)");
sb.AppendLine("{");
sb.AppendLine("string sql = \"update "+tableName+" set "+string.Join(",",par.ToArray())+" where id=@id\";");
sb.AppendLine("int rows = SqlHelper.ExecuteNonQuery(sql");
foreach (DataRow row in dt.Rows)
{
string colName = Convert.ToString(row["COLUMN_NAME"]);
sb.AppendLine(", new SqlParameter(\"" + colName + "\", model." + colName + ")");
}
sb.AppendLine(");");
sb.AppendLine("return rows>0;");
sb.AppendLine("}");


sb.AppendLine("public bool Delete(int id)");
sb.AppendLine("{");
sb.AppendLine("int rows = SqlHelper.ExecuteNonQuery(\"delete from "+tableName+" where id=@id\",");
sb.AppendLine("new SqlParameter(\"id\", id));");
sb.AppendLine("return rows > 0;");
sb.AppendLine("}");

sb.AppendLine("private static "+tableName+" ToModel(DataRow row)");
sb.AppendLine("{");
sb.AppendLine(""+tableName+" model = new "+tableName+"();");
foreach (DataRow row in dt.Rows)
{
string colName = Convert.ToString(row["COLUMN_NAME"]);
string colType = Convert.ToString(row["DATA_TYPE"]);

Type netType = GetTypeByDBType(colType);
string netTypeName;
if (netType.IsValueType)
{
netTypeName = netType + "?";
}
else
{
netTypeName = netType.ToString();
}
sb.AppendLine("model."+colName+" = row.IsNull(\""+colName+"\") ? null : "+"("+netTypeName+")"+"row[\""+colName+"\"];");
}
sb.AppendLine("return model;");
sb.AppendLine("}");



//
sb.AppendLine("public "+tableName+" Get(int id)");
sb.AppendLine("{");
sb.AppendLine("DataTable dt = SqlHelper.ExecuteDataTable(\"select * from "+tableName+" where id=@id\",");
sb.AppendLine("new SqlParameter(\"id\", id));");
sb.AppendLine("if(dt.Rows.Count > 1)");
sb.AppendLine("{");
sb.AppendLine("throw new Exception(\"more than 1 row was found\");");
sb.AppendLine("}");
sb.AppendLine("if(dt.Rows.Count <= 0)");
sb.AppendLine("{");
sb.AppendLine("return null; ");
sb.AppendLine("}");
sb.AppendLine("DataRow row = dt.Rows[0];");
sb.AppendLine(""+tableName+" model = ToModel(row);");
sb.AppendLine("return model;");
sb.AppendLine("}");

sb.AppendLine("public IEnumerable<"+tableName+">ListAll()");
sb.AppendLine("{");
sb.AppendLine("List<"+tableName+"> list = new List<"+tableName+">();");
sb.AppendLine("DataTable dt = SqlHelper.ExecuteDataTable(\"select * from "+tableName+"\");");
sb.AppendLine("foreach (DataRow row in dt.Rows)");
sb.AppendLine("{");
sb.AppendLine("list.Add(ToModel(row));");
sb.AppendLine("}");
sb.AppendLine("return list;");
sb.AppendLine("}");
sb.AppendLine("}");
sb.AppendLine("}");

string DALlDir = Path.Combine(args.OutputDir,"DAL");
string DALFile = Path.Combine(DALlDir,tableName+"DAL.cs");
Directory.CreateDirectory(DALlDir);
File.WriteAllText(DALFile,sb.ToString());
}
private static IEnumerable<string> GetColsWithoutId(List<string> cols)
{
var colArray = from col in cols where col.ToLower() != "id" select col;
return colArray;
}
private static List<string> GetCols(DataTable dt, List<string> cols)
{
foreach (DataRow row in dt.Rows)
{
string colName = Convert.ToString(row["COLUMN_NAME"]);
cols.Add(colName);
}
return cols;
}
复制代码
BLL的实现:
复制代码
        /// <summary>
/// BLL
/// </summary>
/// <param name="args"></param>
/// <param name="tableName"></param>
public static void CreateBLL(CodeBuilderArgs args,string tableName)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("using System;");
sb.AppendLine("using System.Collections.Generic;");
sb.AppendLine("using System.Linq;");
sb.AppendLine("using System.Text;");
sb.AppendLine("using "+args.Namespace+".Model;");
sb.AppendLine("using "+args.Namespace+".DAL;");
sb.AppendLine("namespace "+args.Namespace+".BLL");
sb.AppendLine("{");
sb.AppendLine("partial class "+tableName+"BLL");
sb.AppendLine("{");
sb.AppendLine("public int AddNew("+tableName+" model)");
sb.AppendLine("{");
sb.AppendLine("return new "+tableName+"DAL().AddNew(model);");
sb.AppendLine("}");
sb.AppendLine("public bool Delete(int id)");
sb.AppendLine("{");
sb.AppendLine("return new "+tableName+"DAL().Delete(id);");
sb.AppendLine("}");
sb.AppendLine("public bool Update("+tableName+" model)");
sb.AppendLine("{");
sb.AppendLine("return new "+tableName+"DAL().Update(model);");
sb.AppendLine("}");
sb.AppendLine("public "+tableName+" Get(int id)");
sb.AppendLine("{");
sb.AppendLine("return new "+tableName+"DAL().Get(id);");
sb.AppendLine("}");
sb.AppendLine("public IEnumerable<"+tableName+"> ListAll()");
sb.AppendLine("{");
sb.AppendLine("return new "+tableName+"DAL().ListAll();");
sb.AppendLine("}");
sb.AppendLine("}");
sb.AppendLine("}");
string BLLDir = Path.Combine(args.OutputDir,"BLL");
string BLLFile = Path.Combine(BLLDir,tableName+"BLL.cs");
Directory.CreateDirectory(BLLDir);
File.WriteAllText(BLLFile,sb.ToString());
}
复制代码
详细代码可参考:
本博客为 木宛城主原创,基于 Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 木宛城主(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
分类: 架构思想

本文转自木宛城主博客园博客,原文链接:http://www.cnblogs.com/OceanEyes/archive/2012/03/08/codebuilder.html,如需转载请自行联系原作者
目录
打赏
0
0
0
0
20
分享
相关文章
MyBatis原理分析手写持久层框架1
MyBatis原理分析手写持久层框架1
127 0
AskCodiAI代码生成器
在软件开发领域,提高效率和简化流程是永恒的主题。AskCodi 作为一款基于 OpenAI GPT 的强大 AI 代码生成器,通过提供丰富的应用程序套件和与主流 IDE(如 VS Code、Jetbrains、Sublime Text)的集成,显著提升了编码体验和开发效率。无论初学者还是资深开发者,都可以通过与其交互式对话快速获取所需代码片段、技术支持或解决方案。此外,AskCodi 还具备时间复杂度洞察、自动测试创建等功能,全面支持开发者的各项工作。它不仅简化了复杂的编码查询过程,还鼓励创新,为软件开发带来无限可能。
121 0
CodyAI代码生成器
近年来,人工智能技术飞速发展,Cody这款由Sourcegraph开发的人工智能编码助手应运而生,成为编程领域的一大革新。它不仅能够根据上下文提供精准的代码建议,还能预测开发人员的输入并提供相应代码片段,显著提升编码效率。Cody还能识别潜在错误并提出修复建议,缩短调试时间,同时通过智能代码审查帮助优化代码质量和风格。作为开发人员不可或缺的伙伴,Cody将随着AI技术的进步不断学习和优化,为编程领域带来新的发展机遇。
63 0
探秘MyBatis:手写Mapper代理的源码解析与实现
探秘MyBatis:手写Mapper代理的源码解析与实现
107 1
一文彻底搞懂Mybatis系列(五)之手写Mybatis框架简单探索版(含源代码)
一文彻底搞懂Mybatis系列(五)之手写Mybatis框架简单探索版(含源代码)
120行代码手写一个简单的MyBatis实现简单的CRUD
不用XML只用注解 首先需要创建6个注解 SQL用于输入SQL语句
120 0
逆向工程-MyBatis代码生成器!
阿辉学Java第五个月(2021年三月中旬开始java之旅) SpringBoot 工程下使用 Mybatis 反向工程 拷贝 Mybatis 反向工程配置文件到项目的根目录下
176 0
逆向工程-MyBatis代码生成器!
Mybatis3逆向工程,代码生成器的使用!
Mybatis3逆向工程,代码生成器的使用!
348 0
Mybatis3逆向工程,代码生成器的使用!

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等