SQL Выберите XML из таблицы, как сериализованный словарь - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть структура XML, которую я получил, сериализовав словарь в C #.Я делаю это, чтобы добавить один столбец AdditionalSettings в таблицу против нескольких дополнительных столбцов, и это прекрасно работает.

Структура XML выглядит следующим образом:

<Settings xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Setting>
    <Name>Setting1</Name>
    <Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:boolean">true</Value>
</Setting>
<Setting>
    <Name>Setting2</Name>
    <Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:boolean">true</Value>
</Setting>

Таблица имеет несколько столбцов, подобных этому:

ID (INT)
Setting1 (BIT)
Setting2 (BIT)

Я думаю, что я близок к решению.Это тот SQL, который у меня есть.Проблема в том, что я не получаю пространства имен для элемента Value.

WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS i)
SELECT TOP 1 'Setting1' AS [Setting/Name], 
CASE Setting1 WHEN 1 THEN 'true' ELSE 'false' END AS [Setting/Value]
FROM MyTable
FOR XML PATH('Settings')

Вывод этого SQL выглядит следующим образом:

<Settings xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Setting>
<Name>Setting1</Name>
<Value>true</Value>
</Setting>
</Settings>

РЕДАКТИРОВАТЬ: вместо выполнения SQL дляподдельная таблица, я создал SQL для временной таблицы, которая показывает, что я пытаюсь сделать.

DECLARE @TestTable TABLE (ID INT IDENTITY(1, 1) PRIMARY KEY, [Name] VARCHAR(10), Setting1 BIT, Setting2 BIT)
INSERT INTO @TestTable (Name, Setting1, Setting2)
VALUES
('Test1', 0, 0),
('Test2', 0, 1),
('Test3', 1, 0),
('Test4', 1, 1);

WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS i)
SELECT TOP 1 'Setting1' AS [Setting/Name], 
CASE Setting1 WHEN 1 THEN 'true' ELSE 'false' END AS [Setting/Value]
FROM @TestTable
WHERE Setting1 = 1
FOR XML PATH('Settings')

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Я, наконец, отказался от попыток найти способ сделать это с помощью SQL-запроса, хотя, если кто-то и выяснит это, мне все равно будет интересно узнать ответ.

Я закончил тем, что написалприложение Windows Forms на C # (потому что мне нравится запускать нужный мне код с помощью кнопки, а не более распространенного консольного приложения).

Код для этого следующий, если кому-то интересно.

Это класс AdditionalSettings.

[System.Runtime.Serialization.CollectionDataContract(Namespace = "", Name = "Settings", ItemName = "Setting", KeyName = "Name", ValueName = "Value")]
public class AdditionalSettings : Dictionary<string, object>
{
}

Код ниже:

using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Windows.Forms;

namespace PopulateSettings
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void btnDoThis_Click(object sender, EventArgs e)
        {
            DataTable sources = GetSettings();

            foreach (DataRow dr in sources.Rows)
            {
                AdditionalSettings settings = new AdditionalSettings();

                int settingID = (int)dr["SettingID"];
                bool setting1 = dr["Setting1"] == DBNull.Value ? false : (bool)dr["Setting1"];
                bool setting2 = dr["Setting2"] == DBNull.Value ? false : (bool)dr["Setting2"];
                bool setting3 = (int)dr["Setting3"] == 0 ? false : true;
                bool setting4 = dr["Setting4"] == DBNull.Value ? false : (bool)dr["Setting4"];

                AddToDictionary(settings, "Setting1", setting1);
                AddToDictionary(settings, "Setting2", setting2);
                AddToDictionary(settings, "Setting3", setting3);
                AddToDictionary(settings, "Setting4", setting4);

                string additionalSettings = Serialize<AdditionalSettings>(settings);

                UpdateSources(settingID, additionalSettings);
            }
        }

        private DataTable GetSettings()
        {
            DataTable settings = null;

            string sqlString = @"SELECT SettingID, Setting1, Setting2, Setting3, Setting4
FROM dbo.Settings
WHERE Setting1 = 1
    OR Setting2 = 1
    OR Setting3 = 1
    OR Setting4 = 1";

            using (var cnMy = new SqlConnection(ConfigurationManager.AppSettings["MyConnectionString"]))
            {
                using (var cmd = new SqlCommand(sqlString, cnMy))
                {
                    cmd.CommandType = CommandType.Text;

                    cnMy.Open();
                    using (var da = new SqlDataAdapter(cmd))
                    {
                        settings = new DataTable();
                        da.Fill(settings);
                    }
                }
            }

            return settings;
        }

        private void AddToDictionary(AdditionalSettings dictionary, string name, bool setting)
        {
            if (setting)
            {
                dictionary.Add(name, setting);
            }
        }

        public string Serialize<T>(T Data)
        {
            string strXML = System.String.Empty;

            System.Xml.XmlWriterSettings xmlWriterSettings = new System.Xml.XmlWriterSettings();
            xmlWriterSettings.OmitXmlDeclaration = true;
            xmlWriterSettings.NamespaceHandling = System.Xml.NamespaceHandling.OmitDuplicates;
            xmlWriterSettings.Indent = true;

            var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T));

            System.Text.StringBuilder sbXML = new StringBuilder();

            using (System.IO.StringWriter oStringWriter = new System.IO.StringWriter(sbXML))
            {
                using (System.Xml.XmlWriter xmlWriter = System.Xml.XmlWriter.Create(oStringWriter, xmlWriterSettings))
                {
                    serializer.WriteObject(xmlWriter, Data);
                    xmlWriter.Flush();
                }
                strXML = sbXML.ToString();
            }

            return strXML;
        }

        private void UpdateSources(int settingID, string additionalSettings)
        {
            string sqlString = @"UPDATE dbo.Settings SET AdditionalSettings = @AdditionalSettings WHERE SettingID = @SettingID";

            using (var cnMy = new SqlConnection(ConfigurationManager.AppSettings["MyConnectionString"]))
            {
                using (var cmd = new SqlCommand(sqlString, cnMy))
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.Parameters.Clear();
                    cmd.Parameters.Add("@AdditionalSettings", SqlDbType.VarChar).Value = additionalSettings;
                    cmd.Parameters.Add("@SettingID", SqlDbType.Int).Value = settingID;

                    cnMy.Open();
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
}
0 голосов
/ 07 декабря 2018

Попробуйте изменить:

AS [Setting/Value]

На:

AS 'i:value'

например

WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS i)
SELECT TOP 1 'Setting1' AS 'i:name',
CASE Setting1 WHEN 1 THEN 'true' ELSE 'false' END AS 'i:value'
FROM MyTable
FOR XML PATH('Settings')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...