将SqlDataReader写入XML文件

时间:2015-07-27 21:02:13

标签: c# sql xml sqldatareader

我在C#中测试存储的SQL过程。 procs返回数据类型SqlDataReader,我想将整个事情写入XML文件以便稍后进行比较。我读过的任何内容都没有提供一个非常简单的解决方案。有没有办法在不循环流中的所有数据的情况下执行此操作?我对SQL知之甚少,所以我不确定我到底在做什么。

4 个答案:

答案 0 :(得分:1)

DataSetDataTable及其同类产生的XML从人类阅读它的角度来看还有待改进。我会自己动手。

SqlDataReader(无论是从存储过程返回数据还是纯文本SQL查询)都会返回0到结果集。每个这样的结果集都有

  • 一个架构,用于描述每行中返回的列,以及
  • 结果集本身,由零个或多个组成。
  • 每行基本上是一个包含1个或多个的数组,每个单元格包含行中该序号位置的列的值。
  • 每个此类列都具有某些属性,其中一些属于模式,例如名称,序数类型,可空性等。
  • 最后,行中的列值是与结果中列的SQL Server数据类型对应的类型的object ...如果列为空,则为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. 构建POCO模型类以包含数据。使用XML序列化属性对它们进行属性化以获取所需的标记。从上面的XML示例中,这些类并不是那么复杂。您可能希望将列值表示为字符串而不是本机数据类型。

  3. 构建一个将运行数据读取器并构建模型的映射器。

  4. 然后是几十行代码来构造所选择的XML序列化程序并吐出格式良好的XML。

    备注:

    • 出于质量检查的目的,您可能希望捕获传递给查询的参数(如果有)以及查询本身(可能是运行的日期/时间)。

    • 有一些奇怪的案例,我描述的结果集模型可以得到......不可思议。例如,使用compute by的select语句必须以不同的方式处理。根据我的经验,忽略那种边缘情况是非常安全的,因为你不太可能在野外遇到类似的问题。

    • 考虑一下如何在XML中代表nullnull字符串字符串相同。

答案 1 :(得分: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);
        }
    }
}

答案 2 :(得分:0)

我看到的主要问题是如何在发布之前测试复杂的存储过程,而不是从SQLDataAdapter编写XML,这非常简单。逐行,逐列。 您有一个不包含静态数据的测试数据库,并且您以某种方式存储不同版本的存储过程。 一个简单的设置就是运行你拥有的存储过程的(比如说5个)版本,对它们运行它们 数据库内容,将xmls存储到文件夹并进行比较。我会为每次运行使用一个不同的文件夹,并有一个时间戳来区分它们,例如。我不会花太多时间来编写xmls,为了检测它们是否不同,你最终甚至使用String.Compare(fileStream1.ReadToEnd(),fileStream2.ReadToEnd())。如果结果太大,那么就会有更详细的说明。 如果2 xmls之间存在差异,那么您可以使用文本比较工具查看它们。 ...对于具有多个连接的更复杂的存储过程,最常见的差异可能是xmls的大小\返回的行数,而不是字段的值。

在生产中,数据库的内容不是静态的,所以进行这种类型的测试是没有意义的。

答案 3 :(得分:0)

使用accepted answer中描述的DataTable或DataSet中的内置方法WriteXml序列化SqlDataReader,并且数据包含地理数据时,地理数据丢失且可以&#39后来要恢复。

有关详细信息,请参阅Datatable with SqlGeography column can't be serialized to xml correctly with loss of Lat,Long and other elements

有一种解决方法可以保存到@dbc提供的xml而不会丢失数据,并使用相同的内置方法WriteXml保存到xml。 Try it online