XMLReader в файл XML с использованием XMLWriter WriteNode — очень медленно для больших XML

В С# я использую SqlCommand ExecuteXmlReader() для вызова хранимой процедуры SQL Server, которая использует «For XML» для возврата больших (1 ГБ +) сложных XML-файлов (множественная иерархия).

ExecuteXmlReader() возвращает XmlReader, который я хочу сохранить в файле XML. Для этого я использую XmlWriter для потоковой передачи данных из XMLReader в файловую систему.

using (XmlReader xmlFromDatabase = xmlReaderFromDatabase)
{
  var settings = new XmlWriterSettings {Encoding = Encoding.UTF8, Indent = true};
  using (XmlWriter outputXmlFileToDisk = XmlWriter.Create(fileDirectory + fileName, settings))
  {
    outputXmlFileToDisk.WriteNode(xmlFromDatabase, false);
  }
}

Примечание: я не могу загрузить весь XML в память (XDocument), так как он слишком велик.

Моя проблема в том, что WriteNode очень медленный - запись файла занимает несколько часов. Если я уничтожу свое приложение, XML-файл, записанный на диск, будет частично записан, поскольку файл передается на узел за узлом.

Есть ли лучший способ быстрее сохранить XML из XmlReader, чем из XMLWriter WriteNode?

(Я знаю, что есть .ReadInnerXml(), но это возвращает строку, которая не подходит для размера XML)

После того, как я экспортирую файл, его необходимо преобразовать (я могу использовать Saxon, поскольку .net framework не показал себя столь эффективным, как мне бы хотелось) и проверить его схему с помощью C#.


person Thomas Byrne    schedule 11.01.2017    source источник
comment
Внутренне XML-данные передаются из SQL Server в виде потока символов (через внутренние классы SqlStream и XmlSqlBinaryReader). Поэтому вы можете напрямую скопировать поток в свой выходной поток, используя такой метод: using-c-sharp" title="потоковая передача данных из столбца nvarcharmax с использованием c Sharp">stackoverflow.com/questions/29672383/ (не пробовал, поэтому не публикую это как ответ)   -  person Lucero    schedule 11.01.2017
comment
Кроме того, вы можете взглянуть на пример PrintXmlValuesViaNVarChar, в котором показана горячая поддержка потоковой и асинхронной передачи данных XML через GetTextReader(): msdn.microsoft.com/en-us/library/hh556234(v=vs.110).aspx   -  person Lucero    schedule 11.01.2017
comment
Гораздо быстрее сохранять с помощью инструментов SQL, чем с помощью инструментов C#. Посмотрите на SQLCMD.exe и BCP.exe. См. msdn.microsoft.com/en-us/library/ms162816.aspx   -  person jdweng    schedule 11.01.2017
comment
Работает ли WriteNode медленно или извлечение данных с сервера происходит медленно?   -  person Pawel    schedule 12.01.2017
comment
Извлечение данных из SQL Server происходит довольно быстро, результат XMLReader готов к использованию всего через несколько минут после выполнения команды ExecuteXmlReader. К сожалению, WriteNode при потоковой передаче через XMLReader с использованием XMLWriter занимает несколько часов. Мне нужно сделать это на C#, а не с помощью инструментов SQL Server, потому что требуется другая обработка файлов. Есть ли другой подход или я делаю что-то не так?? SQL Server --> Для запроса XML SQL (большой фрагмент XML) --> XMLReader --> XMLWriter (с использованием WriteNode).   -  person Thomas Byrne    schedule 12.01.2017


Ответы (1)


Я нашел решение, использование XmlReader/XMLWriter кажется хорошим подходом (https://msdn.microsoft.com/en-us/library/ff647804.aspx) только то, что XMLWriter-WriteNode по умолчанию проверяет XML при записи. Поскольку мы знаем, что XML, возвращаемый SQL Server, является допустимым XML, и мы также проверяем XSD весь XML перед его отправкой, нам не нужно, чтобы модуль записи выполнял проверку во время записи. Передача объекта настроек в XMLWriter с CheckCharacters = false предотвращает избыточную проверку и выводит файл всего за несколько минут, а не часов.

var settings = new XmlWriterSettings{
            CheckCharacters = false,
            NewLineHandling = NewLineHandling.None,
            Indent = true,
            Encoding = Encoding.UTF8 };

using (var outputXmlFileToDisk = XmlWriter.Create(fileDirectory + fileName, settings))
{
person Thomas Byrne    schedule 01.02.2017