将 SqlDataReader 写入 XML 文件

Write SqlDataReader to XML file

我正在测试 C# 中存储的 SQL 过程。 procs return 数据类型 SqlDataReader,我想将整个内容写入 XML 文件以便稍后比较。我读过的任何内容都没有提供非常简单的解决方案。有没有办法在不循环遍历流中的所有数据的情况下执行此操作?我对 SQL 了解不多,所以我不确定我在这里工作的确切内容。

试试这个

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);
        }
    }
}

DataSetDataTable 及其同类作品制作的 XML 从人们阅读它的角度来看还有一些不足之处。我会自己动手。

一个SqlDataReader(无论它是从存储过程还是从纯文本SQL查询返回数据都没有关系),returns 0到很多结果集。每个这样的结果集都有

  • 描述每一行中返回的列的模式,并且
  • 结果集本身,包含零个或多个
  • 每一行本质上是一个包含 1 个或多个 列的数组,每个单元格包含在行中具有该序号位置的列的值。
  • 每个这样的列都有特定的属性,一些来自架构,例如名称、序号类型、可空性等。
  • 最后,一行中的列值是 object 类型对应于结果中列的 SQL 服务器数据类型...或 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. 构建一个映射器,它将 运行 数据 reader 并构建您的模型。

然后是几十行代码来构建选择的 XML 序列化器并输出格式良好的 XML.

备注:

  • 出于 QA 目的,您可能希望捕获传递给查询的参数(如果有)以及查询本身,可能 date/time 运行.

  • 在一些奇怪的情况下,我描述的结果集模型可能会变得……不稳定。例如,使用 compute by 的 select 语句必须以不同方式处理。根据我的经验,忽略这种边缘情况是非常安全的,因为你不太可能在野外遇到这样的查询。

  • 想想你如何在 XML 中表示 nullnull 字符串 相同=41=]空个字符串。

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

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

所述,使用DataTable或DataSet中的内置方法WriteXml序列化SqlDataReader时,数据包含地理数据,地理数据丢失 之后无法恢复。

有关详细信息,请阅读

without loss of data and save to xml using the same built-in methods WriteXml. Try it online

提供了一种保存到 xml 的解决方法