SQL Server 2012 XML Type сохраняет значительный пробел

Я пытаюсь сохранить некоторые данные в столбце с типом XML, который, когда данные являются строкой, сохранит точный текст, а не заменит или скорректирует встроенные окончания строк, в частности CR & LF.

Таким образом, строка C#, такая как "A\r\nB\rC\nD", должна возвращаться именно так, но может показаться, что преобразование XML настаивает на замене этих концов строк на LF, что фактически приводит к повреждению данных. Я знаю, почему эта нормализация происходит при чтении XML-файлов и т. Д., Но это не файл, и пробел является значительным.

Я пробовал CONVERT(xml, N'', 1);

Я попытался добавить xml:space="preserve" в качестве атрибута к элементу, содержащему данные.

Я пытался использовать & # x D; на месте ЧР

Для фона:

Я проверяю содержимое строки с помощью CONVERT(varbinary(max), Value) затем скопировать вывод в TextPad, чтобы я мог найти и посмотреть, какие именно символы хранятся.

Я уверен, что данные поступают на SQL Server с окончаниями без изменений (я использую настройки XmlWriter с NewLineHandling = NewLineHandling.None и LLBLGen обрабатывает данные как строку), но не уверен, так как копирование и вставка изменяют окончания, поэтому я не могу их проверить.

Код сериализации Xml в основном заключает в себе словарь

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        var list = new List<Entry>(Values.Count);

        foreach (var entry in Values)
        {
            list.Add(new Entry(entry.Key, entry.Value));
        }

        MementoXmlSerializer.Serialize(writer, list);
    }

    [XmlType("Entry")]
    public struct Entry
    {
        public Entry(string key, object value): this()
        {
            Key = key;
            Value = value;
        }

        [XmlAttribute("key")]
        public string Key { get; set; }

        [XmlElement("Value")]
        public object Value { get; set; }
    }

Где MementoSerializer определяется как:-

static readonly Type[] AdditionalTypes =
{
    typeof(int[]),
    typeof(string[])
};

static readonly XmlSerializer MementoXmlSerializer = new XmlSerializer(typeof(List<Entry>), null, AdditionalTypes, new XmlRootAttribute("Entries"), null);

Шаблон, используемый LLBLGen и видимый в Sql Server Profiler, выглядит следующим образом:

declare @p3 xml
set @p3=convert(xml,N'<Entries xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Entry key="FirmName"><Value xsi:type="xsd:string">A
B
C
D</Value></Entry></Entries>')
exec sp_executesql N'UPDATE [TIPS].[dbo].[Memento] SET [Value]=@p1 WHERE ( [TIPS].[dbo].[Memento].[ID] = @p2)',N'@p1 xml,@p2 int',@p1=@p3,@p2=4

Любая помощь приветствуется.

1 ответ

Может показаться, что экземпляры SqlXml и SqlXmlStreamWrapper, созданные SqlDataReader (по крайней мере, в.Net 4.0), не имеют возможности изменить какие-либо настройки того, как они декодируют двоичные данные Xml, возвращаемые сервером Sql.

Двоичные данные определенно принимаются правильно на стороне клиента, поскольку шестнадцатеричный дамп буфера показывает:

4100 0D00 0A00 4200 0D00 4300 0A00 4400

На данный момент я отказался от идеи иметь памятники с возможностью поиска по xpath. Это было бы хорошо, но мои данные не могут быть надежно обработаны.

Я изменил тип столбца Значение обратно на NVARCHAR(MAX), и теперь все работает нормально.

Другие вопросы по тегам