2012-11-12 51 views
4

我知道通常推薦的方式來從存儲過程填充DataSet實例是使用SqlDataAdapter.Fill(DataSet)。我能夠找到的每一個答案都是以它從盒子裏出來的方式來使用它。通常情況下,我會付諸實施,但效果很好。執行不使用SqlDataAdapter.Fill()返回多個表的存儲過程?

但是,當您需要對存儲過程輸出和DataSet輸入之間的數據進行處理時,它會崩潰。具體來說,在輸出中使用自定義CLR類型時,它將與InvalidOperationException: DataReader.GetFieldType(n) returned null.中斷,其中n是該列的列索引(在其中一個表中,似乎沒有明確的方式來指示列索引引用哪個表) CLR類型的輸出。這是可以理解的,因爲讀者不知道該列中的數據是什麼類型。

我可以打破CLR類型的反序列化邏輯,並在兩個地方使用它,我似乎沒有時間在Fill()分解之前調用任何此類反序列化方法。

我知道約SqlCommand.ExecuteReader(),但似乎只能得到一個表中的一個表。

問題中的CLR類型旨在用一些更嚴格的內容替換核心系統字段之一(目前以自由格式文本存儲)。已經討論過通過數據庫並向這樣的字段的每個返回實例添加方法調用的問題作爲可能性,但肯定會是不重要的工作量。所以有人認爲轉換可以在DAL中完成(只需要以編程方式識別這些列,這是可行的),使存儲對客戶端使用對數據庫仍然透明的數據是透明的。

因此:如何在不使用SqlDataAdapter.Fill()的情況下訪問存儲過程輸出中的所有表? 或者,我該如何掛鉤執行SqlDataAdapter.Fill()來執行SP和填充DataSet之間的手動處理?

回答

2

可以選擇多個表DataReader。您可以使用reader.NextResult,以檢查是否有更多的結果集,並以超前的數據讀取它:

using (var con = new SqlConnection(Properties.Settings.Default.ConnectionString)) 
{ 
    using (var cmd = new SqlCommand("StoredProcedureName", con)) 
    { 
     cmd.CommandType = CommandType.StoredProcedure; 
     int rowCount = 0; 
     con.Open(); 
     using (IDataReader rdr = cmd.ExecuteReader()) 
     { 
      while (rdr.Read()) 
      { 
       Console.WriteLine("Object 1 in Row {0}: '{1}'", ++rowCount, rdr[0]); 
      } 
      if (rdr.NextResult()) 
      { 
       rowCount = 0; 
       while (rdr.Read()) 
       { 
        Console.WriteLine("Object 1 in Row {0}: '{1}'", ++rowCount, rdr[0]); 
       } 
      } 
     } 
    } 
} 
0

它看起來像它實際上是比我想象的更容易。雖然Tim Schmelter's answer讓我進行實驗,但真正的技巧是簡單地將添加到DAL項目的CLR類型程序集。然後,一切都落在SqlDataAdapter.Fill(DataSet);突然間,它知道如何處理從SQL Server收到的二進制數據,顯然(未經驗證,但似乎合理)調用該類型的ToString()。我還沒有驗證在DAL代碼創建在其他地方使用的DataSet時會發生什麼情況,但在這兩者之間,我認爲可以提出一個可行的解決方案。

相關問題