將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;
      }
    }
}

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM