• PCB MS SQL 标量函数(CLR) 实现DataTable转Json方法


     一.准备需转为json字符串的DataTable数据

          在数据库中执行一段SQL返回的数据

              

         需转换后的JSON字符串的效果

    [{"TechName":"开料","ItemName":"综合利用率是否为最高","ItemPara":"/"},{"TechName":"开料","ItemName":"综合利用率","ItemPara":"68.36"},{"TechName":"开料","ItemName":"纬向余料","ItemPara":"0"},{"TechName":"开料","ItemName":"经向余料","ItemPara":"0"},{"TechName":"开料","ItemName":"是否为小交货面积拼板","ItemPara":"n"},{"TechName":"开料","ItemName":"纬向尺寸","ItemPara":"24"},{"TechName":"开料","ItemName":"是否为阴阳铜结构","ItemPara":"N"},{"TechName":"开料","ItemName":"是否横竖开料","ItemPara":"N"},{"TechName":"开料","ItemName":"生产尺寸长","ItemPara":"24"},{"TechName":"开料","ItemName":"生产尺寸宽","ItemPara":"18"},{"TechName":"开料","ItemName":"拼板利用率","ItemPara":"68.36"},{"TechName":"开料","ItemName":"开料图纸","ItemPara":"/"},{"TechName":"开料","ItemName":"是否顾客指定板材","ItemPara":"N"},{"TechName":"开料","ItemName":"开料数","ItemPara":"4"},{"TechName":"开料","ItemName":"大料经向尺寸","ItemPara":"36"},{"TechName":"开料","ItemName":"大料纬向尺寸","ItemPara":"48"},{"TechName":"开料","ItemName":"成品尺寸长","ItemPara":"12"},{"TechName":"开料","ItemName":"成品尺寸宽","ItemPara":"13.5"},{"TechName":"开料","ItemName":"是否为PTFE板材","ItemPara":"N"},{"TechName":"开料","ItemName":"交货拼板个数","ItemPara":"1"},{"TechName":"开料","ItemName":"生产拼板个数","ItemPara":"1176"},{"TechName":"开料","ItemName":"交货单位","ItemPara":"U"},{"TechName":"开料","ItemName":"是否为凹蚀板材","ItemPara":"N"}]

    二.C#写SQL SERVER(CLR)转JSON函数

         先执行SQL返回DataTable,接着再将DataTable转为Json, 这里转为Json有2种方法,代码都贴在下方了

            /// <summary>
            /// 执行SQL语句 返回的DataTable 转为 Json
            /// </summary>
            /// <param name="StrSQL"></param>
            /// <returns></returns>
            [Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
            public static string ExecSQL2Json(string StrSQL)
            {
                DataTable dt = getDataTable(StrSQL);
                //return DataTable2Json(dt);  //方法1    转为 Json
                if (dt is null)
                    return null;
                List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
                foreach (DataRow dr in dt.Rows)
                {
                    Dictionary<string, object> result = new Dictionary<string, object>();
                    foreach (DataColumn dc in dt.Columns)
                    {
                        result.Add(dc.ColumnName, dr[dc].ToString());
                    }
                    list.Add(result);
                }
                return Json.Serialize(list);//方法2    转为 Json
            }
            /// <summary>
            /// 执行SQL获取DataTable
            /// </summary>
            /// <param name="StrSQL"></param>
            /// <returns></returns>
            private static DataTable getDataTable(string StrSQL)
            {
                DataTable dt = new DataTable();
                try
                {
                    using (SqlConnection cn = new SqlConnection("context connection=true"))
                    {
                        using (SqlDataAdapter da = new SqlDataAdapter(StrSQL, cn))
                        {
                            DataSet ds = new DataSet();
                            da.Fill(ds, "tab");
                            dt = ds.Tables["tab"];
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw;
                }
                return dt;
            }
    View Code  

    方法一:DataTable转Json

            /// <summary>
            /// DataTable转Json
            /// </summary>
            /// <param name="table"></param>
            /// <returns></returns>
            public static string DataTable2Json(DataTable table)
            {
                var JsonString = new StringBuilder();
                if (table.Rows.Count > 0)
                {
                    JsonString.Append("[");
                    for (int i = 0; i < table.Rows.Count; i++)
                    {
                        JsonString.Append("{");
                        for (int j = 0; j < table.Columns.Count; j++)
                        {
                            object ValueNull = table.Rows[i][j];
                            if (ValueNull == DBNull.Value)
                            {
                                JsonString.Append(""" + table.Columns[j].ColumnName.ToString() + "":null" + ((j < table.Columns.Count - 1) ? "," : ""));
                            }
                            else
                            {
                                string Value = table.Rows[i][j].ToString();
                                if (table.Columns[j].DataType == typeof(string) || table.Columns[j].DataType == typeof(DateTime) || table.Columns[j].DataType == typeof(Guid))
                                {
                                    JsonString.Append(""" + table.Columns[j].ColumnName.ToString() + "":" + """ + Value + """ + ((j < table.Columns.Count - 1) ? "," : ""));
                                }
                                else
                                {
                                    if (table.Columns[j].DataType == typeof(bool)) Value = Value.ToLower();
                                    JsonString.Append(""" + table.Columns[j].ColumnName.ToString() + "":" + Value + ((j < table.Columns.Count - 1) ? "," : ""));
                                }
                            }
    
                        }
                        JsonString.Append("}" + ((i < table.Rows.Count - 1) ? "," : ""));
                    }
                    JsonString.Append("]");
                }
                return JsonString.ToString();
            }
    View Code

    方法二:  开源MiniJSON类解析Json字符串 

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    
    namespace SQLClr
    {
        /// <summary>
        /// This class encodes and decodes JSON strings.
        /// Spec. details, see http://www.json.org/
        ///
        /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary.
        /// All numbers are parsed to doubles.
        /// </summary>
        public static class Json
        {
            /// <summary>
            /// Parses the string json into a value
            /// </summary>
            /// <param name="json">A JSON string.</param>
            /// <returns>An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false</returns>
            //反序列化
            public static object Deserialize(string json)
            {
                // save the string for debug information
                if (json == null)
                {
                    return null;
                }
    
                return Parser.Parse(json);
            }
            //阻止其他类从该类继承
            sealed class Parser : IDisposable
            {
                const string WORD_BREAK = "{}[],:"";
    
                public static bool IsWordBreak(char c)
                {
                    //     如果 c 是空白,则为 true;否则,为 false;报告指定 Unicode 字符在此字符串中的第一个匹配项的索引。
                    return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1;
                }
    
                enum TOKEN
                {
                    NONE,
                    CURLY_OPEN,
                    CURLY_CLOSE,
                    SQUARED_OPEN,
                    SQUARED_CLOSE,
                    COLON,
                    COMMA,
                    STRING,
                    NUMBER,
                    TRUE,
                    FALSE,
                    NULL
                };
                //     实现从字符串进行读取的 System.IO.TextReader。
                StringReader json;
    
                Parser(string jsonString)
                {
                    json = new StringReader(jsonString);
                }
    
                public static object Parse(string jsonString)
                {
                    using (var instance = new Parser(jsonString))
                    {
                        return instance.ParseValue();
                    }
                }
                //释放
                public void Dispose()
                {
                    json.Dispose();
                    json = null;
                }
    
                Dictionary<string, object> ParseObject()
                {
                    Dictionary<string, object> table = new Dictionary<string, object>();
    
                    // ditch opening brace
                    json.Read();
    
                    // {
                    while (true)
                    {
                        switch (NextToken)
                        {
                            case TOKEN.NONE:
                                return null;
                            case TOKEN.COMMA:
                                continue;
                            case TOKEN.CURLY_CLOSE:
                                return table;
                            default:
                                // name
                                string name = ParseString();
                                if (name == null)
                                {
                                    return null;
                                }
    
                                // :
                                if (NextToken != TOKEN.COLON)
                                {
                                    return null;
                                }
                                // ditch the colon
                                json.Read();
    
                                // value
                                table[name] = ParseValue();
                                break;
                        }
                    }
                }
    
                List<object> ParseArray()
                {
                    List<object> array = new List<object>();
    
                    // ditch opening bracket
                    json.Read();
    
                    // [
                    bool parsing = true;
                    while (parsing)
                    {
                        TOKEN nextToken = NextToken;
    
                        switch (nextToken)
                        {
                            case TOKEN.NONE:
                                return null;
                            case TOKEN.COMMA:
                                continue;
                            case TOKEN.SQUARED_CLOSE:
                                parsing = false;
                                break;
                            default:
                                object value = ParseByToken(nextToken);
    
                                array.Add(value);
                                break;
                        }
                    }
    
                    return array;
                }
    
                object ParseValue()
                {
                    TOKEN nextToken = NextToken;
                    return ParseByToken(nextToken);
                }
    
                object ParseByToken(TOKEN token)
                {
                    switch (token)
                    {
                        case TOKEN.STRING:
                            return ParseString();
                        case TOKEN.NUMBER:
                            return ParseNumber();
                        case TOKEN.CURLY_OPEN:
                            return ParseObject();
                        case TOKEN.SQUARED_OPEN:
                            return ParseArray();
                        case TOKEN.TRUE:
                            return true;
                        case TOKEN.FALSE:
                            return false;
                        case TOKEN.NULL:
                            return null;
                        default:
                            return null;
                    }
                }
    
                string ParseString()
                {
                    StringBuilder s = new StringBuilder();
                    char c;
    
                    // ditch opening quote
                    json.Read();
    
                    bool parsing = true;
                    while (parsing)
                    {
    
                        if (json.Peek() == -1)
                        {
                            parsing = false;
                            break;
                        }
    
                        c = NextChar;
                        switch (c)
                        {
                            case '"':
                                parsing = false;
                                break;
                            case '\':
                                if (json.Peek() == -1)
                                {
                                    parsing = false;
                                    break;
                                }
    
                                c = NextChar;
                                switch (c)
                                {
                                    case '"':
                                    case '\':
                                    case '/':
                                        s.Append(c);
                                        break;
                                    case 'b':
                                        s.Append('');
                                        break;
                                    case 'f':
                                        s.Append('f');
                                        break;
                                    case 'n':
                                        s.Append('
    ');
                                        break;
                                    case 'r':
                                        s.Append('
    ');
                                        break;
                                    case 't':
                                        s.Append('	');
                                        break;
                                    case 'u':
                                        var hex = new char[4];
    
                                        for (int i = 0; i < 4; i++)
                                        {
                                            hex[i] = NextChar;
                                        }
    
                                        s.Append((char)Convert.ToInt32(new string(hex), 16));
                                        break;
                                }
                                break;
                            default:
                                s.Append(c);
                                break;
                        }
                    }
    
                    return s.ToString();
                }
    
                object ParseNumber()
                {
                    string number = NextWord;
                    // 摘要:
                    //     报告指定 Unicode 字符在此字符串中的第一个匹配项的索引。
                    //
                    // 参数:
                    //   value:
                    //     要查找的 Unicode 字符。
                    //
                    // 返回结果:
                    //     如果找到该字符,则为 value 的从零开始的索引位置;如果未找到,则为 -1。
                    if (number.IndexOf('.') == -1)
                    {
                        long parsedInt;
                        //     将数字的字符串表示形式转换为它的等效 64 位有符号整数。一个指示转换是否成功的返回值。
                        Int64.TryParse(number, out parsedInt);
                        return parsedInt;
                    }
    
                    double parsedDouble;
                    Double.TryParse(number, out parsedDouble);
                    return parsedDouble;
                }
                //
                void EatWhitespace()
                {
                    //指示指定字符串中位于指定位置处的字符是否属于空白类别。
                    while (Char.IsWhiteSpace(PeekChar))
                    {
                        json.Read();
                        //摘要:
                        //     返回下一个可用的字符,但不使用它。
                        //
                        // 返回结果:
                        //     表示下一个要读取的字符的整数,或者,如果没有更多的可用字符或该流不支持查找,则为 -1。
                        if (json.Peek() == -1)
                        {
                            break;
                        }
                    }
                }
    
                char PeekChar
                {
                    get
                    {
                        //     读取输入字符串中的下一个字符并将该字符的位置提升一个字符。
                        //
                        // 返回结果:
                        //     基础字符串中的下一个字符,或者如果没有更多的可用字符,则为 -1。
                        return Convert.ToChar(json.Peek());
                    }
                }
    
                char NextChar
                {
                    get
                    {
                        return Convert.ToChar(json.Read());
                    }
                }
    
                string NextWord
                {
                    get
                    {
                        //     表示可变字符字符串。无法继承此类。
                        StringBuilder word = new StringBuilder();
    
                        while (!IsWordBreak(PeekChar))
                        {
                            // 摘要:
                            //     在此实例的结尾追加指定 Unicode 字符的字符串表示形式。
                            //
                            // 参数:
                            //   value:
                            //     要追加的 Unicode 字符。
                            //
                            // 返回结果:
                            //     完成追加操作后对此实例的引用。
                            word.Append(NextChar);
                            //下一个字符为空
                            if (json.Peek() == -1)
                            {
                                break;
                            }
                        }
                        //
                        return word.ToString();
                    }
                }
    
                TOKEN NextToken
                {
                    get
                    {
                        EatWhitespace();
    
                        if (json.Peek() == -1)
                        {
                            return TOKEN.NONE;
                        }
    
                        switch (PeekChar)
                        {
                            case '{':
                                return TOKEN.CURLY_OPEN;
                            case '}':
                                json.Read();
                                return TOKEN.CURLY_CLOSE;
                            case '[':
                                return TOKEN.SQUARED_OPEN;
                            case ']':
                                json.Read();
                                return TOKEN.SQUARED_CLOSE;
                            case ',':
                                json.Read();
                                return TOKEN.COMMA;
                            case '"':
                                return TOKEN.STRING;
                            case ':':
                                return TOKEN.COLON;
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                            case '-':
                                return TOKEN.NUMBER;
                        }
    
                        switch (NextWord)
                        {
                            case "false":
                                return TOKEN.FALSE;
                            case "true":
                                return TOKEN.TRUE;
                            case "null":
                                return TOKEN.NULL;
                        }
    
                        return TOKEN.NONE;
                    }
                }
            }
    
            /// <summary>
            /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string
            /// </summary>
            /// <param name="json">A Dictionary<string, object> / List<object></param>
            /// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
            public static string Serialize(object obj)
            {
                return Serializer.Serialize(obj);
            }
    
            sealed class Serializer
            {
                StringBuilder builder;
    
                Serializer()
                {
                    //创建生成器
                    builder = new StringBuilder();
                }
                //序列化
                public static string Serialize(object obj)
                {
                    var instance = new Serializer();
    
                    instance.SerializeValue(obj);
    
                    return instance.builder.ToString();
                }
                //类型
                void SerializeValue(object value)
                {
                    IList asList;
                    IDictionary asDict;
                    string asStr;
    
                    if (value == null)
                    {
                        builder.Append("null");
                    }
                    else if ((asStr = value as string) != null)
                    {
                        SerializeString(asStr);
                    }
                    else if (value is bool)
                    {
                        builder.Append((bool)value ? "true" : "false");
                    }
                    else if ((asList = value as IList) != null)
                    {
                        SerializeArray(asList);
                    }
                    else if ((asDict = value as IDictionary) != null)
                    {
                        SerializeObject(asDict);
                    }
                    else if (value is char)
                    {
                        SerializeString(new string((char)value, 1));
                    }
                    else
                    {
                        SerializeOther(value);
                    }
                }
                //序列化对象
                void SerializeObject(IDictionary obj)
                {
                    bool first = true;
    
                    builder.Append('{');
    
                    foreach (object e in obj.Keys)
                    {
                        if (!first)
                        {
                            builder.Append(',');
                        }
    
                        SerializeString(e.ToString());
                        builder.Append(':');
    
                        SerializeValue(obj[e]);
    
                        first = false;
                    }
    
                    builder.Append('}');
                }
                // 序列化数组
                void SerializeArray(IList anArray)
                {
                    builder.Append('[');
    
                    bool first = true;
    
                    foreach (object obj in anArray)
                    {
                        if (!first)
                        {
                            builder.Append(',');
                        }
    
                        SerializeValue(obj);
    
                        first = false;
                    }
    
                    builder.Append(']');
                }
                //string
                void SerializeString(string str)
                {
                    builder.Append('"');
    
                    char[] charArray = str.ToCharArray();
                    foreach (var c in charArray)
                    {
                        switch (c)
                        {
                            case '"':
                                builder.Append("\"");
                                break;
                            case '\':
                                builder.Append("\\");
                                break;
                            case '':
                                builder.Append("\b");
                                break;
                            case 'f':
                                builder.Append("\f");
                                break;
                            case '
    ':
                                builder.Append("\n");
                                break;
                            case '
    ':
                                builder.Append("\r");
                                break;
                            case '	':
                                builder.Append("\t");
                                break;
                            default:
                                int codepoint = Convert.ToInt32(c);
                                if ((codepoint >= 32) && (codepoint <= 126))
                                {
                                    builder.Append(c);
                                }
                                else
                                {
                                    //builder.Append("\u");
                                    //builder.Append(codepoint.ToString("x4"));
                                    builder.Append(c);
                                }
                                break;
                        }
                    }
    
                    builder.Append('"');
                }
                //其他
                void SerializeOther(object value)
                {
                    // NOTE: decimals lose precision during serialization.
                    // They always have, I'm just letting you know.
                    // Previously floats and doubles lost precision too.
                    //注意:小数在序列化过程中丢失精度。
                    //他们总是有,我只是让你知道。
                    //以前失去精度和双精度浮点数。
                    if (value is float)
                    {
                        builder.Append(((float)value).ToString("R"));
                    }
                    else if (value is int
                      || value is uint
                      || value is long
                      || value is sbyte
                      || value is byte
                      || value is short
                      || value is ushort
                      || value is ulong)
                    {
                        builder.Append(value);
                    }
                    else if (value is double
                      || value is decimal)
                    {
                        builder.Append(Convert.ToDouble(value).ToString("R"));
                    }
                    else
                    {
                        SerializeString(value.ToString());
                    }
                }
            }
        }
    }
    View Code

    三.SQL服务器CLR配置(允许SQL调用.net程序)

        sp_configure 'show advanced options', 1; 
        RECONFIGURE WITH override
        GO 
        sp_configure 'clr enabled', 1; 
        RECONFIGURE WITH override
        GO
        Sp_changedbowner 'sa',true   --sa改为当前登入用户名
        alter database [dbname] set trustworthy on    --bbname 改为自己的库名

    四.注册 CLR 程序集

       create  ASSEMBLY SQLfunctionAssembly   
       FROM 'D:SQLClr.dll'      --改为自己C#写的dll路径填写
       WITH PERMISSION_SET = UNSAFE;   

            创建的.net程序集数据会写入下表:

      select * from sys.assemblies 
      select  * from sys.assembly_files

        

    五.创建标量函数

    create  FUNCTION [dbo].[ExecSQL2Json](@StrSQL [nvarchar](max))
    RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
    AS 
    EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[ExecSQL2Json]

    六.测试DataTable转Json函数

    DECLARE @SQL VARCHAR(MAX)
    SET @SQL = 'SELECT TechName,ItemName,ItemPara 
                FROM FP_EMS_DB.dbo.V_ppegeneral 
                WHERE pdctno = ''2V011Z30A4'' AND TechNo = ''CC_01'' ORDER BY ItemNo '
    SELECT  dbo.ExecSQL2Json(@SQL)

         运行后结果

    七.小结

         采用CLR方式写SQL SERVER函数转为json字符串,那么只要传入一段SQL语句就可以转为Json字符串,是不是很方便,但这种作法在实际应用中作用不太大,因为业务系统现在基本采用ORM 对象关系映射模型开发,数据库表映射成对象,直接操作的对象,然而对象转为json放在应用程序端转换是及为方便的,在这里只开拓一种新思路在数据库中实现转json的方法。

  • 相关阅读:
    hdu-5492 Find a path(dp)
    hdu-5493 Queue(二分+树状数组)
    bzoj-2243 2243: [SDOI2011]染色(树链剖分)
    codeforces 724
    codeforces 422A A. Borya and Hanabi(暴力)
    codeforces 442C C. Artem and Array(贪心)
    codeforces 442B B. Andrey and Problem(贪心)
    hdu-5918 Sequence I(kmp)
    poj-3739. Special Squares(二维前缀和)
    hdu-5927 Auxiliary Set(树形dp)
  • 原文地址:https://www.cnblogs.com/pcbren/p/10122190.html
Copyright © 2020-2023  润新知