簡體   English   中英

將SqlDataReader寫入XML文件

[英]Write SqlDataReader to XML file

我正在用C#測試存儲的SQL過程。 proc返回數據類型SqlDataReader,我想將整個內容寫到XML文件中以便以后進行比較。 我讀過的任何文章都沒有提供一個非常簡單的解決方案。 有沒有一種方法可以在不循環訪問流中所有數據的情況下進行此操作? 我對SQL不太了解,所以我不確定我在這里使用什么。

DataSetDataTable及其同類產品產生的XML從人類閱讀XML的角度來看是令人不滿意的。 我會自己動手。

SqlDataReader (無論它從存儲過程返回的數據還是純文本SQL查詢都沒有關系),它對許多結果集返回0。 每個這樣的結果集都有

  • 描述每行要返回的列的模式 ,以及
  • 結果集本身,包含零個或多個
  • 每行本質上是1 或更多的數組,每個單元格包含該行中該順序位置的列的值。
  • 每個此類列都具有某些屬性,某些屬性來自架構,例如名稱,順序類型,可空性等。
  • 最后,一行中的列值是對應於結果中列的SQL Server數據類型的object ,如果DbNull.Value null, 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. 構建一個映射器,該映射器將運行數據讀取器並構建您的模型。

然后,用幾十行代碼來構造所選的XML序列化器並吐出格式正確的XML。

筆記:

  • 為了進行質量檢查,您可能希望捕獲傳遞給查詢的參數(如果有)以及查詢本身(可能是運行的日期/時間)。

  • 在一些奇怪的情況下,我描述的結果集模型可能會變得...很奇怪。 例如,使用compute by的select語句在處理方式上有所不同。 以我的經驗,忽略這種極端情況是非常安全的,因為您不太可能在野外遇到類似的查詢。

  • 想想你如何表示null的XML: null字符串是一樣的字符串。

嘗試這個

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

我看到的主要問題是如何在發行前測試復雜的存儲過程,而不是從SQLDataAdapter編寫XML,這可能非常簡單。 逐行,逐列。 您有一個不包含靜態數據的測試數據庫,並且以某種方式存儲了不同版本的存儲過程。 一個簡單的設置是運行(擁有5個)存儲過程的版本,針對相同的數據庫內容運行它們,將xml存儲到文件夾中並進行比較。 例如,每次運行時我都會使用一個不同的文件夾,並有一個時間戳來區分它們。 我不會在xml的寫法上花太多錢,並且為了檢測它們是否不同,即使使用String.Compare(fileStream1.ReadToEnd(),fileStream2.ReadToEnd()),也最終會花費很多。 如果結果太大,則需要進一步詳細說明。 如果2個xml之間存在差異,則可以使用文本比較工具查看它們。 ...對於具有多個聯接的更復雜的存儲過程,最常見的區別可能是xmls \\返回的行數而不是字段的值。

在生產中,數據庫的內容不是靜態的,因此進行這種類型的測試是沒有意義的。

接受的答案中所述,使用DataTable或DataSet中的內置方法WriteXml對SqlDataReader進行序列化時,並且該數據包含地理數據,則地理數據將丟失 ,並且以后無法還原。

有關更多詳細信息,請參見帶有SqlGeography的Datatable列,由於丟失了Lat,Long和其他元素,因此無法正確地序列化為xml

有一種解決方法,可以保存到@dbc提供的xml而不丟失數據,並使用相同的內置方法WriteXml保存到xml。 在線嘗試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM