zoukankan      html  css  js  c++  java
  • 【开源.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

  • 相关阅读:
    3.Appium运行时出现:Original error: Android devices must be of API level 17 or higher. Please change your device to Selendroid or upgrade Android on your device
    3.Python连接数据库PyMySQL
    2.Python输入pip命令出现Unknown or unsupported command 'install'问题解决
    2.Linux下安装Jenkins
    5.JMeter测试mysql数据库
    Android 4学习(7):用户界面
    Android 4学习(6):概述
    Android 4学习(5):概述
    Android 4学习(4):概述
    Android 4学习(3):概述
  • 原文地址:https://www.cnblogs.com/grissom007/p/6496865.html
Copyright © 2011-2022 走看看