2015-07-27 3 views
0

Я тестирую хранимые процедуры SQL на C#. Процессы возвращают тип данных SqlDataReader, и я хочу записать все это в XML-файл, который будет потом сравнивать. Ничто из того, что я прочитал, не дает очень простого решения. Есть ли способ сделать это, не зацикливая все данные в потоке? Я мало что знаю о SQL, поэтому я не уверен, что я здесь делаю.Запись файла SqlDataReader в XML

+1

Набор данных или datatable можно легко записать в XML. DataSet и DataTable извлекают все результаты в память сразу - поэтому, если ваши результаты не слишком велики, чтобы вписаться в память, вы можете переключиться на них вместо DataReader. –

+0

Можно заметить, что XML-схема, используемая 'DataSet', оставляет желать лучшего с точки зрения удобочитаемости человека. Это имеет значение, если ваш человек QA пытается проверить и разобраться. –

ответ

0

Попробуйте

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 
using System.Data.SqlClient; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     const string FILENAME = @"C:\temp\test.xml"; 
     static void Main(string[] args) 
     { 
      string connstr = "Enter your connection string here"; 
      string SQL = "Enter your SQL Here"; 

      SqlDataAdapter adapter = new SqlDataAdapter(SQL, connstr); 
      SqlCommand cmd = adapter.SelectCommand; 
      cmd.Parameters.Add("abc", SqlDbType.VarChar); 


      adapter.SelectCommand.ExecuteNonQuery(); 

      DataSet ds = new DataSet(); 
      adapter.Fill(ds); 

      ds.WriteXml(FILENAME, XmlWriteMode.WriteSchema); 
     } 
    } 
} 
+0

Как добавить параметры для запуска с этим? В качестве альтернативы, я собрал метод преобразования SqlDataReader в DataSet, но по какой-то причине он будет извлекать только типы данных как RunTimeType –

+0

Обновленный код для включения параметров – jdweng

+0

Хорошо спасибо. DataAdapter и DataReader настолько похожи.Во всяком случае, я получил конвертер DataSet для работы, но я могу вернуться к этому, если он заканчивается слишком долго для запуска. –

1

XML, произведенный DataSet, DataTable и его иже оставляет желать лучшего с точки зрения людей, читающих его. Я бы бросил свой собственный.

A SqlDataReader (и не имеет значения, возвращаются ли его возвращаемые данные из хранимой процедуры или SQL-запроса с открытым текстом), возвращает 0 ко многим наборам результатов. Каждый такой результат набор

  • схемы, которая описывает столбцы возвращаются в каждой строке, и
  • результирующий набор себя, состоящий из нуля или более строк .
  • Каждая строка, по существу, представляет собой массив из 1 или более столбцов , причем каждая ячейка содержит значение для столбца с этим порядковым положением в строке.
  • каждый такой столбца имеет определенные свойства, некоторые из схемы, такие как имя, порядковый тип, допустимость пустые и т.п.
  • Наконец, значение столбца в строке, является object типа, соответствующим данным SQL Server тип столбца в результате ... или DbNull.Value, если столбец равен нулю.

Основной цикл довольно проста (много примеров в MSDN о том, как это сделать.) И в то время как это могло бы быть немного работы, чтобы написать это в первую очередь, когда-то написал, это использовать поперек доска, так что это одноразовый удар. Я бы предложил сделать что-то вроде этого:

  1. Определите, как вы хотите, чтобы XML выглядел. Если предположить, что намерение состоит в том, чтобы иметь возможность дифф результаты время от времени, я бы, вероятно, пойти с чем-то, что выглядит следующим образом (так как я люблю держать вещи лаконична и избежать избыточности):

    <stored-procedure-results> 
        <name> dbo.some-stored-procedure-name </name> 
        <result-sets> 
        <result-set> 
         <column-schema column-count="N"> 
         <column ordinal="0...N-1" name="column-name-or-null-if-column-is-unnamed-or-not-unique" data-type=".net-data-type" nullable="true|false" /> 
         ... 
         </schema> 
         <rows> 
         <row> 
          <column ordinal="0..N-1" value="..." /> 
          ... 
         <row/> 
         ... 
         </rows> 
        </result-set> 
        ... 
        </result-sets> 
    </stored-procedure-results> 
    
  2. Построить ПОКО классы моделей для хранения данных. Присвойте их атрибутам сериализации XML, чтобы получить необходимую разметку. Из приведенного выше примера XML эти классы не будут такими сложными. Вероятно, вы захотите представить значения столбцов как строки, а не собственные типы данных.

  3. Создайте картограф, который будет запускать устройство чтения данных и построить вашу модель.

Тогда это несколько десятков строк кода, чтобы построить сериализатор XML по выбору и выколоть хорошо отформатированный XML.

Примечания:

  • В целях обеспечения качества, вы можете захотеть, чтобы захватить параметры, если таковые имеются, которые были переданы в запросе, а сам запрос, возможно, дата/время бег.

  • Есть несколько случайных случаев, когда модель набора результатов, которую я описываю, может получить ... wonky. Например, оператор select, использующий compute by, должен обрабатываться несколько иначе. По моему опыту, довольно безопасно игнорировать этот случай с краем, поскольку вы вряд ли столкнетесь с подобными запросами в дикой природе.

  • Подумайте о том, как вы представляете null в XML: null строки не такой же, как пустых строк.

0

Я вижу, что основная проблема заключается в том, как проверить сложные хранимые процедуры перед выпуском, а не писать XML из SQLDataAdapter, что может быть очень простым. Строка по строке, по столбцу. У вас есть тестовая база данных, которая не содержит статических данных, и вы храните как-то разные версии хранимой процедуры. Простой настройкой было бы запустить (допустим, 5) версии хранимой процедуры, которую вы используете, запустить их с тем же содержимым базы данных , сохранить xmls в папку и сравнить их. Я бы использовал, например, другую папку для каждого прогона и имел временную метку, чтобы отличать их, например. Я бы не потратил слишком много на то, как написаны xmls, и чтобы определить, являются ли они разными, вы даже используете String.Compare (fileStream1.ReadToEnd(), fileStream2.ReadToEnd()). Если результат слишком велик, то что-то более подробно. Если есть разница между 2 xmls, вы можете посмотреть на них с помощью инструмента сравнения текста. ... Для более сложных хранимых процедур с несколькими объединениями наиболее распространенной разницей будет, скорее всего, размер xmls \ числа возвращенных строк, а не значение поля.

В процессе производства содержимое базы данных не является статическим, поэтому этот тип теста не имеет смысла.

+0

Это идея, я просто не могу получить созданные файлы , –

0

При сериализации SqlDataReader с помощью встроенных методов WriteXml в DataTable или DataSet, как описано в accepted answer, и данные содержат географию данных, то географические данные теряются и не могут быть восстановлены последней.

Для более подробной информации читайте Datatable with SqlGeography column can't be serialized to xml correctly with loss of Lat,Long and other elements

Там обходной путь решения, чтобы сохранить в XML, представленной @dbc без потери данных и сохранить в XML с использованием тех же встроенных методов WriteXml. Try it online

Смежные вопросы