該篇是 Grissom.CMS 框架系列文章的第三篇, 主要介紹框架用到的核心庫 EasyJsonToSql, 把標準的配置文件和數據結構解析成可執行的 sql。
該框架能實現自動化增刪改查得益於 EasyJsonToSql 類庫的功能:解析配置好的表結構和要進行數據庫操做的數據,生成 sql,減小普通的增刪改查代碼量,簡化「數據庫 - 後端- 前端」之間的交互。html
【開源.NET】 輕量級內容管理框架Grissom.CMS(第一篇分享一個先後端分離框架)
【開源.NET】 輕量級內容管理框架Grissom.CMS(第二篇先後端交互數據結構分析)
【開源.NET】 輕量級內容管理框架Grissom.CMS(第三篇解析配置文件和數據以轉換成 sql)前端
Nuget 命令git
Install-Package EasyJsonToSql
或Nuget 界面搜索: EasyJsonToSql
或下載源碼(看文章底部)github
1) 假設有一張表sql
CREATE TABLE `BasUser` ( `Id` bigint(20) NOT NULL AUTO_INCREMENT, `Name` varchar(64) DEFAULT NULL, PRIMARY KEY (`Id`) );
2) 後臺配置 sqlconfig數據庫
const string sqlJson = @" { ""Select"":""user.*"", ""From"":""BasUser user"", ""Where"":{ ""Fields"":[ {""Name"":""Name"",""Cp"":""like""} ] }, ""OrderBy"":{""Default"":""Id""}, ""ID"":""Id"", ""Table"":""BasUser"", ""Insert"":{ ""Fields"":[ {""Name"":""Name"",""IsIgnore"":""false""} ] } } ";
3) 查詢 reqeust url: http://localhost:9819/api/user/get?name=test
json
public dynamic Get(string name) { var dt = new DataTable(); // 用 json 的配置 var sqlconfig = JsonConvert.DeserializeObject<SqlConfig>(sqlJson); var sqlSb = new StringBuilder(); var nameValues = new NameValueCollection(); nameValues.Add("name", name); var builder = new Proxy().ToSelectBuilder(sqlconfig, nameValues); var builderData = builder.Data; sqlSb.AppendFormat("Select {0} From {1} Where {2}", builderData.Select, builderData.From, builderData.Where); using (var da = new MySqlDataAdapter(sqlSb.ToString(), cnnStr)) { da.Fill(dt); } return dt; }
返回結果: [{"Id":1,"Name":"test4"},{"Id":2,"Name":"test1"},{"Id":3,"Name":"test1"},{"Id":4,"Name":"test7"}]
後端
4) 新增 post url: http://localhost:9819/api/user/post
, form data: {"master":{"inserted":[{"data":{"Name":"test1"}}]}}
api
public dynamic Post() { var json = ""; using (StreamReader sr = new StreamReader(HttpContext.Current.Request.InputStream)) { json = sr.ReadToEnd(); } var jobj = JObject.Parse(json); // json 的配置 var sqlconfig = JsonConvert.DeserializeObject<SqlConfig>(sqlJson); var builder = new Proxy().ToDbBuilders(sqlconfig, jobj); var insertSqlSb = new StringBuilder(); //獲取第一個sqlconfig var data = builder[0].Data; insertSqlSb.AppendFormat("insert into {0}(", data.TableName); var valueSqlSb = new StringBuilder(); var paras = new List<MySqlParameter>(); foreach (var dbField in data.Fields) { // 不是自增的字段才添加 if (!dbField.IsId) { insertSqlSb.AppendFormat("{0}", dbField.DbName); valueSqlSb.AppendFormat("@{0}", dbField.DbName); paras.Add(new MySqlParameter("@" + dbField.DbName, dbField.Value)); } } insertSqlSb.AppendFormat(") values({0})", valueSqlSb); var affectCount = 0; using (var cnn = new MySqlConnection(cnnStr)) { using (var cmd = new MySqlCommand(insertSqlSb.ToString(), cnn)) { cnn.Open(); cmd.Parameters.AddRange(paras.ToArray()); affectCount = cmd.ExecuteNonQuery(); } } return affectCount; }
上面可看到 get 和 post 方法是脫離業務的,全部業務都在 sqlJson 配置和 前端返回的 json 數據,從而實現了後臺配置化操做數據庫,不需建立額外的對象,就能夠把前端返回的json 數據, 直接持久化到數據庫了。bash
這個類是 EasyJsonToSql 入口,用來獲取 SelectBuilder 和 DbBuilder 對象。
1) 獲取 SelectBuilder
const string sqlJson = @" { ""Select"":""user.*"", ""From"":""BasUser user"", ""Where"":{ ""Fields"":[ {""Name"":""Name"",""Cp"":""like""} ] }, ""OrderBy"":{""Default"":""Id""}, ""ID"":""Id"", ""Table"":""BasUser"", ""Insert"":{ ""Fields"":[ {""Name"":""Name"",""IsIgnore"":""false""} ] } } "; var sqlconfig = JsonConvert.DeserializeObject<SqlConfig>(sqlJson); var builder = new Proxy().ToSelectBuilder(sqlconfig, nameValues);
2) 獲取 DbBuilder
// 插入數據 var postJson = @"{""master"":{""inserted"":[{""data"":{""Name"":""abc1""}}]}}"; var jobj = JObject.Parse(postJson); var sqlconfig = JsonConvert.DeserializeObject<SqlConfig>(sqlJson); var builder = new Proxy().ToDbBuilders(sqlconfig, jobj);
該類負責處理查詢分析,把 json 轉換成查詢的 sql。
1) Data[SelectBuilderData]: 生成的 sql 對象。
1) AddWhere: 添加 where 條件 sql,
builder.AddWhere("And table1.Id = 1"); builder.AddWhere("And table1.Id = @Id").AddParam("Id",1);
2) AddParam: 添加參數, builder.AddParam("Id",1)
var data = builder.Data; var sql = string.format("Select {0} From {1} Where {2}", data.Select, data.From, data.Where);
該類負責處理增刪改分析,把 json 轉換成增刪改的 sql。
1) Data[BuilderData]: 生成的 sql 對象。
1) AddChild: 添加子表對象。
2) AddWhere: 添加 where 條件 sql;
builder.AddWhere("And table1.Id = 1"); builder.AddWhere("And table1.Id = @Id").AddParam("Id", 1);
3) AddParam: 添加參數, builder.AddParam("Id",1)
;
該類保存 select、from、where、insert、update、delete, 以及子表、依賴關係、自增字段、主鍵等 sql 相關對象,標準化 sql 配置以便脫離具體業務。
用來初始化 SelectBuilder 和 DBBuilder, 實現標準化的增刪改查操做。
上面就是用 json 配置的來反射出 SqlConfig, var sqlconfig = JsonConvert.DeserializeObject<SqlConfig>(sqlJson);
public class SqlConfig { public SqlConfig() { this.Where = new Where(); this.Children = new List<SqlConfig>(); this.OrderBy = new OrderBy(); this.GroupBy = new GroupBy(); this.Dependency = new Dependency(); this.Insert = new Insert(); this.Update = new Update(); this.Delete = new Delete(); this.SingleQuery = new SingleQuery(); this.Export = new Export(); this.Import = new Import(); this.BillCodeRule = new BillCodeRule(); } private string _settingName; /// <summary> /// 配置名稱,默認和表名一致,通常不會用到,方法之後擴展,如一個配置文件出現相同的表時,用來區分不一樣的配置 /// </summary> public string SettingName { get { if (string.IsNullOrEmpty(_settingName)) { _settingName = Table; } return _settingName; } set { _settingName = value; } } #region 查詢配置 /// <summary> /// 查詢的字段 /// </summary> public string Select { get; set; } /// <summary> /// 查詢的表名以及關聯的表名,如 left join, right join /// </summary> public string From { get; set; } /// <summary> /// 查詢的條件 /// 前端返回的查詢條件,只有出如今這些配置好的字段,纔會生成爲了 sql 的 where 條件, /// 沒出現的字段會被忽略 /// </summary> public Where Where { get; set; } /// <summary> /// 分頁時必須會乃至的排序規則 /// </summary> public OrderBy OrderBy { get; set; } public GroupBy GroupBy { get; set; } /// <summary> /// 頁碼 /// </summary> public int PageNumber { get; set; } /// <summary> /// 頁大小 /// </summary> public int PageSize { get; set; } #endregion 查詢配置 /// <summary> /// 指定該配置所屬於的表 /// </summary> public string Table { get; set; } #region 增刪改配置 /// <summary> /// 對應前端返回的 json 格式數據的鍵名 /// e.g.: {master:{inserted:[{data:{}}]}} 中的 master 就是這裏要對應的 JsonName /// 注意默認主表的 jsonName 是 master, 因此主表通常可省略不寫, 但子表必須得指定 /// </summary> public string JsonName { get; set; } /// <summary> /// 自增的字段,指定了自增的字段,在 insert 時會自動忽略該字段 /// </summary> public string ID { get; set; } /// <summary> /// 主鍵, 在保存成功後會返回主鍵的值; /// </summary> public string PKs { get; set; } /// <summary> /// 惟一值的字段,對應數據庫 unique, 在 insert,update 前會判斷是否已存在 /// </summary> public string Uniques { get; set; } /// <summary> /// 惟一值的字段的值是否容許爲空 /// </summary> public string UniqueAllowEmptys { get; set; } /// <summary> /// 所屬的父級配置, 在 xml 中不用指定,程序會自動分析 /// </summary> public SqlConfig Parent { get; set; } /// <summary> /// 包含的子級配置, 即子表的配置,須要在 xml 中配置 /// </summary> public List<SqlConfig> Children { get; set; } /// <summary> /// 依賴父表的字段 /// </summary> public Dependency Dependency { get; set; } /// <summary> /// insert 的配置 /// </summary> public Insert Insert { get; set; } /// <summary> /// update 的配置 /// </summary> public Update Update { get; set; } /// <summary> /// delete 的配置 /// </summary> public Delete Delete { get; set; } #endregion /// <summary> /// 單條記錄查詢的配置,通常用在配置列表雙擊彈出那條記錄的獲取的 sql /// </summary> public SingleQuery SingleQuery { get; set; } /// <summary> /// 導出配置 /// </summary> public Export Export { get; set; } /// <summary> /// 導入配置 /// </summary> public Import Import { get; set; } /// <summary> /// 是否物理刪除? /// </summary> public bool DeleteAnyway { get; set; } /// <summary> /// 表單編碼的生成配置 /// </summary> public BillCodeRule BillCodeRule { get; set; } }
能夠用 xml、json 或對象來配置表關係,若是用了 xml 或 json配置, 把它反射成對象便可。
1) xml 配置
string sqlXml = @" <SqlConfig> <Select> user.* </Select> <From> BasUser user </From> <Where> <Fields> <Field Name=""Name"" Cp=""like""></Field> </Fields> </Where> <OrderBy> <Default>Id</Default> </OrderBy> <IDs>Id</IDs> <PKs>Id</PKs> <Table>BasUser</Table> <Insert> <Fields> <Field Name=""Name"" IsIgnore=""false""></Field> </Fields> </Insert> </SqlConfig> ";
2) json 配置
string sqlJson = @" { ""Select"":""user.*"", ""From"":""BasUser user"", ""Where"":{ ""Fields"":[ {""Name"":""Name"",""Cp"":""like""} ] }, ""OrderBy"":{""Default"":""Id""}, ""ID"":""Id"", ""PKs"":""Id"", ""Table"":""BasUser"", ""Insert"":{ ""Fields"":[ {""Name"":""Name"",""IsIgnore"":""false""} ] } } "; var sqlconfig = JsonConvert.DeserializeObject<SqlConfig>(sqlJson);
初始化登陸名:admin, 密碼: 123