C++语法复杂,写一个示例通过T4可生成c++代码

需求:数据库,生成c++增,删,改,查代码

  1. 数据生成c++类,包含所有字段
  2. 自动识别数据的主键Key
  3. 查询生成赋值类字段,类型转换
  4. 通过类自动生成sql的where条件
  5. 类改变一些字段值,自动生成update sql
  6. 生成所有字段打印代码
class Actor_Entry;      //数据库实体类
class Actor_UpdateEntry;//更新实体类
class Actor //实体增,删,改,查类
{
public:
bool Select(MYSQL* connect, const std::string& sql, std::vector<Actor_Entry>& out);
bool SelectAll(MYSQL* connect, std::vector<Actor_Entry>& v);
bool Update(MYSQL* connect, const Actor_UpdateEntry& set, const Actor_UpdateEntry& where, const std::string& whereSql);
bool Update(MYSQL* connect, const std::string& whereSql);
bool Insert(MYSQL* connect, Actor_UpdateEntry& v);
bool Delete(MYSQL* connect, const Actor_UpdateEntry& v);
};
class Actor_Entry
{
public:
std::string ToString();
static Actor_Entry& New();//方便拷贝代码
short int GetKey() const;
// 数据字段,及类型映射
// 主键(自动识别主键)
short int Actor_Id;
std::string First_Name;
std::string Last_Name;
std::string Last_Update;
};
//字段发生改变,自动生成sql
class Actor_UpdateEntry : public Actor_Entry
{
public:
Actor_UpdateEntry();
static Actor_UpdateEntry& New();//方便拷贝代码
bool IsModified() const;
void ResetModified();
void Set_Actor_Id(const short int value);
bool Actor_Id_Modified; void Set_First_Name(const std::string& value);
bool First_Name_Modified; void Set_Last_Name(const std::string& value);
bool Last_Name_Modified; void Set_Last_Update(const std::string& value);
bool Last_Update_Modified;
};

  

一个数据库,不到10s生成7000+行代码

实现方式:

读取表结构:

        public static IEnumerable<TABLE_SCHEMA_> GetTableSchemaEnumerable(MySqlConnectionStringBuilder builder)
{
using (var conn = GetConnection(builder))
{
var sql =
$"SELECT DISTINCT t.`TABLE_COMMENT`, c.* FROM information_schema.`COLUMNS` as c INNER join INFORMATION_SCHEMA.`TABLES` t on c.`TABLE_NAME`= t.`TABLE_NAME` where c.TABLE_SCHEMA = '{builder.Database}';"; using (var cmd = conn.CreateCommand())
{
cmd.CommandText = sql; using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var obj = new TABLE_SCHEMA_();
obj.TABLE_COMMENT = reader[nameof(obj.TABLE_COMMENT)].DbCast<string>();
obj.TABLE_NAME = reader[nameof(obj.TABLE_NAME)].DbCast<string>();
obj.TABLE_CATALOG = reader[nameof(obj.TABLE_CATALOG)];
obj.TABLE_SCHEMA = reader[nameof(obj.TABLE_SCHEMA)];
obj.TABLE_NAME = reader[nameof(obj.TABLE_NAME)].DbCast<string>();
obj.COLUMN_NAME = reader[nameof(obj.COLUMN_NAME)].DbCast<string>();
obj.ORDINAL_POSITION = reader[nameof(obj.ORDINAL_POSITION)].DbCast<uint>();
obj.COLUMN_DEFAULT = reader[nameof(obj.COLUMN_DEFAULT)];
{
var v = reader[nameof(obj.IS_NULLABLE)];
obj.IS_NULLABLE = "Yes".EqualsByIgnoreCaseEx(v.DbCast<string>());
}
obj.DATA_TYPE = reader[nameof(obj.DATA_TYPE)].DbCast<string>();
obj.CHARACTER_MAXIMUM_LENGTH = reader[nameof(obj.CHARACTER_MAXIMUM_LENGTH)].DbCast<long?>();
obj.CHARACTER_OCTET_LENGTH = reader[nameof(obj.CHARACTER_OCTET_LENGTH)].DbCast<long?>();
obj.NUMERIC_PRECISION = reader[nameof(obj.NUMERIC_PRECISION)];
obj.NUMERIC_SCALE = reader[nameof(obj.NUMERIC_SCALE)];
obj.DATETIME_PRECISION = reader[nameof(obj.DATETIME_PRECISION)];
obj.CHARACTER_SET_NAME = reader[nameof(obj.CHARACTER_SET_NAME)].DbCast<string>();
obj.COLLATION_NAME = reader[nameof(obj.COLLATION_NAME)].DbCast<string>();
obj.COLUMN_TYPE = reader[nameof(obj.COLUMN_TYPE)].DbCast<string>();
obj.COLUMN_KEY = reader[nameof(obj.COLUMN_KEY)].DbCast<string>();
obj.EXTRA = reader[nameof(obj.EXTRA)];
obj.PRIVILEGES = reader[nameof(obj.PRIVILEGES)];
obj.COLUMN_COMMENT = reader[nameof(obj.COLUMN_COMMENT)].DbCast<string>();
obj.GENERATION_EXPRESSION = reader[nameof(obj.GENERATION_EXPRESSION)];
obj.SRS_ID = reader[nameof(obj.SRS_ID)];
yield return obj;
}
}
}
}
}

用t4生成c++代码:

bool <#= className #>::Insert(MYSQL* connect, <#= tab.ClassName_UpdateEntry #>& v)
{
if(!v.IsModified())
{
return false;
}
std::string f;
std::string values;
<#+
var isOneKey = tab.Keys.Length == 1;//判断是不是单主键
foreach (var field in tab.FieldsSupported)
{
var type = field.Type;
var name = field.Name;
#>
if (v.<#=field.NameModify#>)
{
f += " `<#=field.ColumnName#>`,";
values += std::format(" '{}',", v.<#=field.Name#>);
}
<#+
}
#>
<#+if(isOneKey){//自增主键,自动写入insert的生成的key#>
{
std::string sql = std::format("insert into `<#=tab.TabName#>` ({}) values({});", f.substr(0, f.length() - 1), values.substr(0, values.length() - 1));
int query = mysql_query(connect, sql.c_str());
// if (!query) return false;
}
{
std::string sql = "SELECT LAST_INSERT_ID() as id;";
int query = mysql_query(connect, sql.c_str());
// if (!query) return false;
} auto res = mysql_use_result(connect);
if(res == nullptr) return false; MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != nullptr)
{
v.<#=tab.Keys[0].Name#> = Columns::GetInt(row, 0);
break;
}
mysql_free_result(res);
<#+}else{#>
std::string sql = std::format("insert into `<#=tab.TabName#>` ({}) values({});", f.substr(0, f.length() - 1), values.substr(0, values.length() - 1));
int query = mysql_query(connect, sql.c_str());
if (!query) return false;
<#+}#>
return true;
}

(c++代码多年没写,有可能有误,只是为了测试T4)

Roslyn+T4+EnvDTE ,基本上可以从一种数据源生成,另一种任意格式文本格式

视频演示

代码

提取码:ynpb

Roslyn+T4+EnvDTE项目完全自动化(3) ——生成c++代码的更多相关文章

  1. Roslyn+T4+EnvDTE项目完全自动化 (一)

    前言 以前做一个金融软件项目,软件要英文.繁体版本,开始甲方弄了好几个月,手动一条一条替换,发现很容易出错,因为有金融专业术语,字符串在不同语义要特殊处理,第三方工具没法使用.最后我用Roslyn写了 ...

  2. 在maven项目中使用mybatis-generator-maven-plugin生成mybatis代码

    项目整体的目录结构如下: pom.xml如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...

  3. MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码

    前言 经过前面EF的<第一篇>与<第二篇>,我们的数据层功能已经较为完善了,但有不少代码相似度较高,比如负责实体映射的 EntityConfiguration,负责仓储操作的I ...

  4. 利用PowerShell+Jenkins,实现项目的自动化部署

    当项目越来越庞大,部署环境越来越多以后,就会越来越依赖于自动化.比如本人公司的项目,目前有6个web和4个windows service,同时本地有两套环境:开发自测试环境和QA测试环境.每次版本发布 ...

  5. [转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码

    本文转自:http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html 〇.目录 一.前言 二.工具准备 三.T4代码生成预热 (一) 单文件生成:Hello ...

  6. Roslyn 入门:使用 Roslyn 静态分析现有项目中的代码

    Roslyn 是微软为 C# 设计的一套分析器,它具有很强的扩展性.以至于我们只需要编写很少量的代码便能够分析我们的项目文件. 作为 Roslyn 入门篇文章,你将可以通过本文学习如何开始编写一个 R ...

  7. 使用Git实现Laravel项目的自动化部署

    简介 不知道大家一开始是怎么使用 git 进行开发的,反正我个人是先将代码提交到 github 仓库,然后用 SSH 登录到服务器,然后进行克隆或者版本更新.听起来就很麻烦,当然实际操作中也很麻烦,那 ...

  8. 聊聊 Web 项目二维码生成的最佳姿势

    在设计和实现的过程之后,你永远不知道部署上去的程序会已什么样的姿势运行. 本篇借一次生成二维码逻辑的不同实现,阐述 Web 项目中二维码生成的正确姿势. 文中如有批量,欢迎各位看客老爷拍砖.试运行前5 ...

  9. AppVeyor-CI为GitHub项目做自动化集成(dotnet为主)

    travis-ci对dotnet的项目做自动化集成不太友好,尤其是使用mono的编译和不能使用MSTest进行自动化测试,所以转到appveyor进行. appveyor的配置非常简单,有两种方式: ...

随机推荐

  1. Android 极光推送集成

    集成Jpush 1.用Android Studio创建一个Demo 2.创建激光推送开发者账号,要创建极光推送开发者帐号,请访问极光推送官方网站https://www.jiguang.cn/push ...

  2. 机器学习——sklearn中的API

    import matplotlib.pyplot as pltfrom sklearn.svm import SVCfrom sklearn.model_selection import Strati ...

  3. Java动态脚本Groovy,高级啊!

    前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 简介: Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚 ...

  4. 阿里云RDS备份 恢复到本地

    目录 一.恢复准备 二.具体操作 一.恢复准备 阿里云RDS默认配置了全备份+binlog,可以精准恢复到某个时间点上. 可以下载备份的包到本地,进行本地恢复,要预留好本地的数据库容量和cpu等规格, ...

  5. Python pyecharts绘制饼图

    一.pyecharts绘制饼图语法简介 饼图主要用于表现不同类目的数据在总和中的占比.每个的弧度不是数据量的占比pie.add()方法的用法add(name, attr, value, radius= ...

  6. [BUUCTF]PWN——ciscn_2019_es_7[详解]

    ciscn_2019_es_7 附件 步骤: 例行检查,64位程序,开启了nx保护 本地试运行一下看看大概的情况 64位ida载入,关键函数很简单,两个系统调用,buf存在溢出 看到系统调用和溢出,想 ...

  7. 工作簿合并(Excel代码集团)

    同一文件夹内N个工作簿 ,每个工作簿里N个工作表,最终合并到一个工作表里的代码. 假设每个表格结构相同,第一行为标题,第二行为表头,表头内容固定,行数不固定,列固定14,工作表数量不固定,工作簿数量不 ...

  8. 2. Go中defer使用注意事项

    1. 简介 defer 会在当前函数返回前执行传入的函数,它会经常被用于关闭文件描述符.关闭数据库连接以及解锁资源. 理解这句话主要在三个方面: 当前函数 返回前执行,当然函数可能没有返回值 传入的函 ...

  9. CF415A Mashmokh and Lights 题解

    Content 有 \(n\) 个灯,一开始都是亮着的. 有 \(m\) 次操作,每次操作按下开关 \(x\),按下之后所有编号 \(\geqslant x\) 的灯全部熄灭.问你所有的灯第一次被熄灭 ...

  10. 反射hasattr; getattr; setattr; delattr

    hasattr(obj,name_str):#判断一个对象obj里面是否有对应的name_str字符串的方法,返回True或者Falsegetattr(obj,name_str):#根据字符串去获取对 ...