該篇是 Grissom.CMS 框架系列文章的第三篇, 主要介紹框架用到的核心庫 EasyJsonToSql, 把標準的配置文件和數據結構解析成可執行的 sql。
該框架能實現自動化增刪改查得益于 EasyJsonToSql 類庫的功能:解析配置好的表結構和要進行數據庫操作的數據,生成 sql,減少普通的增刪改查代碼量,簡化“數據庫 - 后端- 前端”之間的交互。
【開源.NET】 輕量級內容管理框架Grissom.CMS(第一篇分享一個前后端分離框架)
【開源.NET】 輕量級內容管理框架Grissom.CMS(第二篇前后端交互數據結構分析)
【開源.NET】 輕量級內容管理框架Grissom.CMS(第三篇解析配置文件和數據以轉換成 sql)
安裝
Nuget 命令
Install-Package EasyJsonToSql
或Nuget 界面搜索: EasyJsonToSql
或下載源碼(看文章底部)
Kick Start
1) 假設有一張表
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
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"}}]}}
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 數據, 直接持久化到數據庫了。
簡介
Proxy
這個類是 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);
SelectBuilder
該類負責處理查詢分析,把 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);
DbBuilder
該類負責處理增刪改分析,把 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)
;
SqlConfig
該類保存 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);
Grissom.CMS框架源碼 https://github.com/grissomlau/Grissom.CMS
初始化登錄名:admin, 密碼: 123
EasyJsonToSql類庫源碼 https://github.com/grissomlau/EasyJsonToSql
文章列表