• 【开源.NET】轻量级内容管理框架Grissom.CMS(第三篇解析配置文件和数据以转换成 sql)


    该篇是 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`)
    );
    
    1. 后台配置 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""}
                    ]
                }
            }
        ";
    
    1. 查询 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"}]

    1. 新增 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);
    
    
    1. 获取 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);
    
    1. 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);
    
    1. 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>
                ";
    
    1. 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

  • 相关阅读:
    Android 自定义Adapter中实现startActivityForResult的分析
    上周热点回顾(11.30-12.6)团队
    .NET跨平台之旅:基于.NET Core改写EnyimMemcached,实现Linux上访问memcached缓存团队
    上周热点回顾(11.23-11.29)团队
    上周热点回顾(11.16-11.22)团队
    .NET跨平台之旅:在Linux上将ASP.NET 5运行日志写入文件团队
    .NET跨平台之旅:增加文件日志功能遇到的挫折团队
    .NET跨平台之旅:升级至ASP.NET 5 RC1,Linux上访问SQL Server数据库团队
    上周热点回顾(11.9-11.15)团队
    上周热点回顾(11.2-11.8)团队
  • 原文地址:https://www.cnblogs.com/grissom007/p/6496865.html
Copyright © 2020-2023  润新知