C++語法複雜,寫一個示例通過T4可生成c++程式碼
需求:資料庫,生成c++增,刪,改,查程式碼
- 資料生成c++類,包含所有欄位
- 自動識別資料的主鍵Key
- 查詢生成賦值類欄位,型別轉換
- 通過類自動生成sql的where條件
- 類改變一些欄位值,自動生成update sql
- 生成所有欄位列印程式碼
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