我在C#中测试存储的SQL过程。 procs返回数据类型SqlDataReader,我想将整个事情写入XML文件以便稍后进行比较。我读过的任何内容都没有提供一个非常简单的解决方案。有没有办法在不循环流中的所有数据的情况下执行此操作?我对SQL知之甚少,所以我不确定我到底在做什么。
答案 0 :(得分:1)
由DataSet
,DataTable
及其同类产生的XML从人类阅读它的角度来看还有待改进。我会自己动手。
SqlDataReader
(无论是从存储过程返回数据还是纯文本SQL查询)都会返回0到结果集。每个这样的结果集都有
object
...如果列为空,则为DbNull.Value
。 基本循环非常简单(在MSDN中有很多关于如何操作的例子。)虽然首先编写它可能有点工作,但一旦编写,它可以全面使用,所以这是一次性打击。我建议做这样的事情:
确定您希望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>
构建POCO模型类以包含数据。使用XML序列化属性对它们进行属性化以获取所需的标记。从上面的XML示例中,这些类并不是那么复杂。您可能希望将列值表示为字符串而不是本机数据类型。
构建一个将运行数据读取器并构建模型的映射器。
然后是几十行代码来构造所选择的XML序列化程序并吐出格式良好的XML。
备注:强>
出于质量检查的目的,您可能希望捕获传递给查询的参数(如果有)以及查询本身(可能是运行的日期/时间)。
有一些奇怪的案例,我描述的结果集模型可以得到......不可思议。例如,使用compute by
的select语句必须以不同的方式处理。根据我的经验,忽略那种边缘情况是非常安全的,因为你不太可能在野外遇到类似的问题。
考虑一下如何在XML中代表null
:null
字符串不与空字符串相同。
答案 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后来要恢复。
有一种解决方法可以保存到@dbc提供的xml而不会丢失数据,并使用相同的内置方法WriteXml保存到xml。 Try it online