Roslyn+T4+EnvDTE项目完全自动化(3) ——生成c++代码


(视频演示  代码 提取码:ynpb)

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 ,基本上可以从一种数据源生成,另一种任意格式文本格式

引用来源:https://www.cnblogs.com/metoget/p/15758961.html

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
管理员
上一篇:C# 执行Javascript脚本
下一篇:使用.NET 6开发TodoList应用(15)——实现查询搜索
评论列表

发表评论

评论内容
昵称:
关联文章

Roslyn+T4+EnvDTE项目完全自动化(3) ——生成c++代码
Roslyn+T4+EnvDTE项目完全自动化(1) ——类自动生成界面
.NET Core 运行时T4模板使用,T4生成代码
C# 使用Roslyn编译项目 .csproj
C# Roslyn编译csproj项目 使用Roslyn编译整个C#项目
利用代码生成工具Database2Sharp生成ABP VNext框架项目代码
FastReport完全破解--asp.net使用签名问题
C#代码编码规范手册 软件开发规范 开发指南
MH/T4029.3 IFPL报文解析
bat脚本:生成项目并自动加壳发布
C# 读取txt文件生成Word文档
分享一个自研开发的QA自动化审计工具-Sonar检查
解决.Net Core3.0 修改cshtml代码之后必须重新生成才可以看到效果
.NET Core 项目调试的时候不能修改代码
生成随机数
C# 7.0 - C# 7.3 中的新增功能
.NET中大型项目开发必备(4)--数据库的读写分离
YESWin Winform开发框架 代码生成器使用
.NET Reactor代码混淆注意事项
VUE Cli3项目添加LESS支持

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码