将json对象数据保存到数据库对应的表中

问题描述 

如何将json对象数据保存到数据库对应的表中。

分析问题  

json数据内容不固定,json数据格式是固定的(name:value),数据库表结构是固定的,在json数据格式 与 数据库表结构之间建立一套对应规则,写一套逻辑解析这套对应规则。

1、json对象对应的数据库表需要确定。

2、json对象的节点对应数据库表的列需要确定。

3、json对象的value类型需要确定下来,才能对value值做相应的操作。

4、数据库表的主键列比较特殊,一般是自增长列,需要确定。

5、数据库记录一般是假删除,有一个删除状态列,需要确定。

6、json对象的value的类型是json时,此列为外键,确定主表,获取主表主键。

7、json对象的value的类型是array是,json此节点的数据为从表的数据,确定从表,对从表操作。

解决问题实例

一、自定义特性

定义了两个特性,EntityAttribute特性用于实体,PropertyAttribute特性用于属性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Standard.Frame.BEntity
{
    /// <summary>
    /// 实体特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class EntityAttribute : Attribute
    {
        public EntityAttribute(String entityName, String tableName)
        {
            EntityName = entityName;
            TableName = tableName;
        }

        /// <summary>
        /// 实体名称
        /// </summary>
        public string EntityName { get; set; }

        /// <summary>
        /// 表名称
        /// </summary>
        public string TableName { get; set; }
    }

    /// <summary>
    /// 属性特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class PropertyAttribute : Attribute
    {
        public PropertyAttribute() { }

        /// <summary>
        /// json节点名称
        /// </summary>
        public string FieldName { get; set; }

        /// <summary>
        /// 列名称
        /// </summary>
        public string ColumnName { get; set; }

        /// <summary>
        /// 节点类型
        /// </summary>
        public string NodeType { get; set; }

        /// <summary>
        /// 是否是主键
        /// </summary>
        public string IsPK { get; set; }

        /// <summary>
        /// 是否删除
        /// </summary>
        public string IsDeletedFlag { get; set; }

        /// <summary>
        /// 主实体
        /// </summary>
        public string MainEntity { get; set; }
    }

}

  

二、在实体、属性上添加特性

这里特性的作用:

 1、建立json对象与数据库表的对应关系。

2、建立json节点的name与数据库表列的对应关系。

3、指定json节点value的类型,类型主要有三类:字符串、json对象、数组。

4、标示出主键列。

5、标示出删除标示列。

6、标示出主实体列,类似于关系表的外键关系。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Standard.Frame.Config;

namespace Standard.Frame.BEntity
{
    /// <summary>
    /// 项目信息
    /// </summary>
    [Entity("PlanProject", "XMGL_20")]
    public class PlanProject:BaseBEntity
    {
        /// <summary>
        /// 项目ID
        /// </summary>
        [Property(FieldName = "planProjectID", ColumnName = "XMGL_20_COL_10", NodeType = NodeType.String, IsPK = BooleanType.True)]
        public string PlanProjectID { get; set; }

       /// <summary>
        /// 项目名称
        /// </summary>
        [Property(FieldName = "planProjectName", ColumnName = "XMGL_20_COL_70", NodeType = NodeType.String)]
        public string PlanProjectName { get; set; }
     /// <summary>
        /// 是否已删除
        /// </summary>
        [Property(FieldName = NodeOperation.Operation, ColumnName = "XMGL_20_COL_200", NodeType = NodeType.String, IsDeletedFlag = BooleanType.True)]
        public string IsDeleted { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        [Property(FieldName = "createTime", ColumnName = "XMGL_20_COL_210", NodeType = NodeType.String)]
        public string CreateTime { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        [Property(FieldName = "creatorID", ColumnName = "XMGL_20_COL_220", NodeType = NodeType.Json, MainEntity = "User")]
        public string CreatorID { get; set; }

        /// <summary>
        /// 项目组成员
        /// </summary>
        [Property(FieldName = "projectMember", NodeType = NodeType.Array, MainEntity = "ProjectMember")]
        public string ProjectMember { get; set; }
    }

    /// <summary>
    /// 项目组成员信息
    /// </summary>
    [Entity("ProjectMember", "XMGL_220")]
    public class ProjectMember : BaseBEntity
    {
        /// <summary>
        /// 人员ID
        /// </summary>
        [Property(FieldName = "projectMemberID", ColumnName = "XMGL_220_COL_10", NodeType = NodeType.String, IsPK = BooleanType.True)]
        public string ProjectMemberID { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        [Property(FieldName = "projectMemberName", ColumnName = "XMGL_220_COL_20", NodeType = NodeType.String)]
        public string ProjectMemberName { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        [Property(FieldName = "sex", ColumnName = "XMGL_220_COL_30", NodeType = NodeType.String)]
        public string Sex { get; set; }
        /// <summary>
        ///  备注
        /// </summary>
        [Property(FieldName = "notes", ColumnName = "XMGL_220_COL_110", NodeType = NodeType.String)]
        public string Notes { get; set; }

        /// <summary>
        /// 是否已删除
        /// </summary>
        [Property(FieldName = NodeOperation.Operation, ColumnName = "XMGL_220_COL_200", NodeType = NodeType.String, IsDeletedFlag = BooleanType.True)]
        public string IsDeleted { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        [Property(FieldName = "createTime", ColumnName = "XMGL_220_COL_210", NodeType = NodeType.String)]
        public string CreateTime { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        [Property(FieldName = "creatorID", ColumnName = "XMGL_220_COL_220", NodeType = NodeType.Json, MainEntity = "User")]
        public string CreatorID { get; set; }

        /// <summary>
        /// 项目
        /// </summary>
        [Property(FieldName = "planProject", ColumnName = "XMGL_20_COL_10", NodeType = NodeType.Json, MainEntity = "PlanProject")]
        public string PlanProject { get; set; }

    }
}

三、反射机制,分析实体特性、属性特性,将json对象数据保存到数据库。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Standard.Frame.BEntity;
using Standard.Frame.Utility;
using Standard.Frame.Config;
using Standard.Frame.DBAccess;
using System.Reflection;
using Standard.Frame.Utility;

namespace Standard.Frame.BLRuler
{
    public class JsonToTable
    {
        public static void Save(object inputJsonObj)
        {
            try
            {
                SaveJsonObj(inputJsonObj, "PlanProject", null);
            }
            catch (Exception e)
            {
                LogUtility.Write(DateTime.Now.ToString() + " : " + e.Message);
            }

        }

        /// <summary>
        /// 保存输入的json对象
        /// </summary>
        /// <param name="inputJsonObj"></param>
        /// <param name="entityName"></param>
        private static void SaveJsonObj(object inputJsonObj, string entityName, Tuple<string, object> tupleFk)
        {
            Dictionary<string, object> dicReq = CommonFacade.ParseJsonObjToDic(inputJsonObj);

            Type type = CommonFacade.GetEntityType(entityName);
            string tableName = CommonFacade.GetTableNameByType(type);
            System.Reflection.PropertyInfo[] properties = type.GetProperties();

            //先保存主表数据(string类型的节点)
            object recordID = SaveStringNode(dicReq, tableName, properties, tupleFk);

            //保存从表数据(array类型的节点)
            SaveArrayNode(dicReq, properties, entityName, recordID);
        }

        /// <summary>
        /// 保存json对象中的字符串节点
        /// </summary>
        /// <param name="dicReq"></param>
        /// <param name="tableName"></param>
        /// <param name="properties"></param>
        /// <param name="tupleFk"></param>
        /// <returns></returns>
        private static object SaveStringNode(Dictionary<string, object> dicReq, string tableName, System.Reflection.PropertyInfo[] properties,Tuple<string, object> tupleFk)
        {
            PreSqlAccess sqlAccess = new PreSqlAccess();
            Dictionary<string, object> dicTable = new Dictionary<string, object>();
            Tuple<string, object> tuplePk = ParseStringNode(dicReq, properties, dicTable);
            if (tupleFk != null)
            {
                dicTable.Remove(tupleFk.Item1);
                dicTable.Add(tupleFk.Item1, tupleFk.Item2);
            }
            object recordID = sqlAccess.InsertOrUpdateDataSync(tableName, dicTable, tuplePk);//保存到数据库
            return recordID;
        }

        /// <summary>
        /// 保存从表数据(数据类型为array的节点)
        /// </summary>
        /// <param name="dicReq"></param>
        /// <param name="properties"></param>
        /// <param name="recordID"></param>
        private static void SaveArrayNode(Dictionary<string, object> dicReq, System.Reflection.PropertyInfo[] properties, string mainEntityName, object recordID)
        {
            System.Attribute[] attrs = null;
            foreach (System.Reflection.PropertyInfo p in properties)
            {
                attrs = System.Attribute.GetCustomAttributes(p);
                foreach (System.Attribute attr in attrs)
                {
                    if (attr is PropertyAttribute)
                    {
                        PropertyAttribute propertyAttr = (PropertyAttribute)attr;
                        if (dicReq.ContainsKey(propertyAttr.FieldName) && propertyAttr.NodeType == NodeType.Array)
                        {
                            Tuple<string, object> tupleFk = GetTupleFKID(propertyAttr.MainEntity, mainEntityName, recordID);
                            List<object> listObj = CommonFacade.ParseJsonObjToList(dicReq[propertyAttr.FieldName]);
                            listObj.ForEach((inputJsonObj) =>
                            {
                                SaveJsonObj(inputJsonObj, propertyAttr.MainEntity, tupleFk);
                            });
                        }
                    }
                }
            }
        }

        /// <summary>/// 解析输入json对象中的字符串节点
        /// </summary>
        /// <param name="dicReq"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        private static Tuple<string, object> ParseStringNode(Dictionary<string, object> dicReq, System.Reflection.PropertyInfo[] properties, Dictionary<string, object> dicTable)
        {
            Tuple<string, object> tuplePk = null;
            System.Attribute[] attrs = null;
            foreach (System.Reflection.PropertyInfo p in properties)
            {
                attrs = System.Attribute.GetCustomAttributes(p);
                foreach (System.Attribute attr in attrs)
                {
                    if (attr is PropertyAttribute)
                    {
                        PropertyAttribute propertyAttr = (PropertyAttribute)attr;
                        if (dicReq.ContainsKey(propertyAttr.FieldName))
                        {
                            if (propertyAttr.IsPK == BooleanType.True)
                            {//记录主键,备用
                                tuplePk = new Tuple<string, object>(propertyAttr.ColumnName, dicReq[propertyAttr.FieldName]);
                                break;
                            }
                            if (propertyAttr.IsDeletedFlag == BooleanType.True)
                            {//"是否删除" 这个标示列需要特殊处理
                                if (dicReq.ContainsKey(NodeOperation.Operation) && Convert.ToString(dicReq[propertyAttr.FieldName]) == NodeOperationType.Deleted)
                                    dicTable.Add(propertyAttr.ColumnName, 1);
                                break;
                            }
                            if (propertyAttr.NodeType == NodeType.String)
                                dicTable.Add(propertyAttr.ColumnName, dicReq[propertyAttr.FieldName]);
                            if (propertyAttr.NodeType == NodeType.Json)
                                dicTable.Add(propertyAttr.ColumnName,CommonFacade.GetPKID(dicReq[propertyAttr.FieldName], propertyAttr.MainEntity));
                        }
                    }
                }
            }
            return tuplePk;
        }

        /// <summary>/// 将主表ID匹配到从表对应的外键
        /// </summary>
        /// <param name="inputJsonObj"></param>
        /// <param name="entityName"></param>
        /// <param name="mainEntityName"></param>
        /// <param name="recordID"></param>
        /// <returns></returns>
        private static Tuple<string, object> GetTupleFKID(string entityName, string mainEntityName, object recordID)
        {
            Tuple<string, object> tupleFK = null;

            Type type = CommonFacade.GetEntityType(entityName);
            System.Reflection.PropertyInfo[] properties = type.GetProperties();
            System.Attribute[] attrs = null;
            foreach (System.Reflection.PropertyInfo p in properties)
            {
                attrs = System.Attribute.GetCustomAttributes(p);
                foreach (System.Attribute attr in attrs)
                {
                    if (attr is PropertyAttribute)
                    {
                        PropertyAttribute propertyAttr = (PropertyAttribute)attr;
                        if (propertyAttr.NodeType == NodeType.Json && propertyAttr.MainEntity == mainEntityName)
                        {
                            tupleFK = new Tuple<string, object>(propertyAttr.ColumnName,recordID);
                            goto outer;
                        }
                    }
                }
            }
        outer:
            return tupleFK;
        }
    }
}

四、操作数据库

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using Standard.Frame.Config;

namespace Standard.Frame.DBAccess
{
   public class PreSqlAccess
    {
       /// <summary>/// 同步插入记录
       /// </summary>
       /// <param name="tablename"></param>
       /// <param name="dicTable"></param>
       /// <returns></returns>
       private object InsertRecordSync(string tablename, Dictionary<string, object> dicTable)
       {
           StringBuilder columns = new StringBuilder();
           StringBuilder datas = new StringBuilder();
           List<IDataParameter> parameters = new List<IDataParameter>();
           foreach (var item in dicTable)
           {
               columns.Append(item.Key).Append(",");
               datas.Append("@" + item.Key).Append(",");
               parameters.Add(new SqlParameter("@" + item.Key, item.Value));
           }

           StringBuilder sqlCommand = new StringBuilder();
           sqlCommand.Append(" insert into ");
           sqlCommand.Append(tablename).Append(" ( ").Append(columns.ToString().Trim(new char[] { ‘,‘ })).Append(" ) ");
           sqlCommand.Append(" values ( ").Append(datas.ToString().Trim(new char[] { ‘,‘ })).Append(" ) ");

           SqlAccess sqlAccess = new SqlAccess();
           return sqlAccess.InsertRecordSync(tablename, sqlCommand.ToString(), CommandType.Text, parameters.ToArray(), null);

       }

       /// <summary>/// 同步更新记录
       /// </summary>
       /// <param name="tablename"></param>
       /// <param name="dicTable"></param>
       /// <param name="tuplePk"></param>
       /// <returns></returns>
       private object UpdateRecordSync(string tablename, Dictionary<string, object> dicTable, Tuple<string, object> tuplePk)
       {
           StringBuilder columnValues = new StringBuilder();
           List<IDataParameter> parameters = new List<IDataParameter>();
           foreach (var item in dicTable)
           {
               columnValues.Append(item.Key).Append("=").Append("@" + item.Key).Append(",");
               parameters.Add(new SqlParameter("@" + item.Key, item.Value));
           }

           StringBuilder sqlCommand = new StringBuilder();
           sqlCommand.Append(" update ").Append(tablename);
           sqlCommand.Append(" set ");
           sqlCommand.Append(columnValues.ToString().Trim(new char[] { ‘,‘ }));
           sqlCommand.Append(" where ").Append(tuplePk.Item1).Append("=").Append(tuplePk.Item2);

           SqlAccess sqlAccess = new SqlAccess();
           return sqlAccess.ExecuteNonQuerySync(sqlCommand.ToString(), CommandType.Text, parameters.ToArray(), null);
       }
       /// <summary>
       /// 插入或者更新记录 返回记录ID
       /// </summary>
       /// <param name="tablename"></param>
       /// <param name="dicTable"></param>
       /// <param name="tuplePk"></param>
       /// <returns></returns>
       public object InsertOrUpdateDataSync(string tablename, Dictionary<string, object> dicTable, Tuple<string, object> tuplePk = null)
      {
          object recordID = default(object);
          if (dicTable.ContainsKey(NodeOperation.Operation))
          {
              switch (Convert.ToString(dicTable[NodeOperation.Operation]))
              {
                  case NodeOperationType.Added:
                      dicTable.Remove(NodeOperation.Operation);
                      recordID=InsertRecordSync(tablename, dicTable);
                      break;
                  case NodeOperationType.Changed:
                  case NodeOperationType.Deleted:
                      dicTable.Remove(NodeOperation.Operation);
                      recordID = tuplePk.Item2;
                      UpdateRecordSync(tablename, dicTable, tuplePk);
                      break;
                  default: ; break;
              }
          }
          return recordID;
      }
    }
}
时间: 2024-12-14 11:59:04

将json对象数据保存到数据库对应的表中的相关文章

pandans导出Excel并将数据保存到不同的Sheet表中

数据存在mongodb中,按照类别导出到Excel文件,问题是想把同一类的数据放到一个sheet表中,最后只导出到一个excel文件中# coding=utf-8import pandas as pd def export_to_excel_bycas(): client = pymongo.MongoClient('localhost', 27017) db = client['****'] coll = db["***"] #之前看到的都收  writer = pd.ExcelWr

把dataGridView数据保存到已有的Excel表中

//先添加引用,步骤:1,引用--COM--Microsoft Excel 14.0 Object Library //14.0是2010版 // 2,using Excel = Microsoft.Office.Interop.Excel; //// 3,using Microsoft.Office.Interop.Excel; // 4,using System.Reflection; private void button1_Click(object sender, EventArgs e

WordPress插件制作教程(四): 将数据保存到数据库

上一篇讲解了添加菜单的方法,这一篇为大家讲解如何将数据保存到数据库中,并且显示在页面上,不会因提交表单时刷新页面输入框中内容消失.要实现这一功能我们需要借助WordPress函数来实现,下面就来讲解具体的实现方法,先把代码贴出来.还是根据之前的那个插件样例,大家可以直接在上面做修改. // 在WordPress后台评论处添加一个子菜单 add_action('admin_menu', 'comments_submenu'); function comments_submenu() { add_c

PHP如何通过Http Post请求发送Json对象数据?

因项目的需要,PHP调用第三方 Java/.Net 写好的 Restful Api,其中有些接口,需要 在发送 POST 请求时,传入对象. Http中传输对象,最好的表现形式莫过于JSON字符串了,但是作为参数的接收方,又是需要被告知传过来的是JSON! 其实这不难,只需要发送一个 http Content-Type头信息即可,即 “Content-Type: application/json; charset=utf-8”,参考代码如下: <?php /** * PHP发送Json对象数据

把数据保存到数据库附加表 `dede_addonarticle` 时出错,请把相关信息提交给DedeCms

把数据保存到数据库附加表 `dede_addonarticle` 时出错,请把相关信息提交给DedeCms官方.Duplicate entry '2′ for key 'PRIMARY' 你的主键是不可重复的,现在重复插入值为3的主键了.可以去掉主键唯一,或是设成自增加.就不会出现这种情况了. 具体操作: 进入后台,"系统" - "系统设置" - "SQL命令行工具" 运行SQL命令行: alter table dede_addonarticle

Ajax请求php返回json对象数据中包含有数字索引和字符串索引,在for in循环中取出数据的顺序问题

//php中的数组数据格式 Array ( [all] => Array ( [title] => ALL [room_promotion_id] => all ) [best_available_rate] => Array ( [title] => Best Available Rate [room_promotion_id] => best_available_rate ) [30] => Array ( [room_promotion_id] =>

富文本域数据保存到数据库

前言:<富文本域数据保存到数据库>,这个标题感觉还不够清晰明了.只好再赘述一遍了,前端使用了bootstrap的wysiwyg富文本组件,然后就是不知道怎么保存图片,图片数据提交到数据库后,在前端无法显示. 今天看到jquery.base64.js,隐隐约约知道了解决方案. 经常不经意间就发现文章被扣到各式各样的网站上面,甚是可恶! 那么人生何处不爬虫,爬虫请标http://blog.csdn.net/qing_gee 见贤思齐焉,见不贤而内自省也! 普通做法 function html_en

dedecms新建内容模型“把数据保存到数据库附加表时出错‘xxx’出错”错误的原因分析和解决方案(转)

把数据保存到数据库附加表 `bc_addonarticle17` 时出错,请把相关信息提交给DedeCms官方.INSERT INTO `bc_addonarticle17`(aid,typeid,redirecturl,templet,userip,body, ) Values( 11 , 11 , , , 127 0 0 1, )You have an error in your 今天在使用dedecms之梦系统进行建站的时候,使用新创建的自定义内容模型来添加文章的时候出现了错误,错误描述如

php中json对象数据的输出转化

php中json对象数据的输出转化 public function get_my_now_citys(){ $datas=$this->_post('datas'); //前台js脚本传递给后端的object对象 if(!$datas){ echo '地址信息获取失败!'; } $latitude=$datas['latitude'];//维度 $longitude=$datas['longitude'];//经度 $rs=$this->get_my_addr_infos($longitude