2016-08-19 91 views
0

我目前打電話給sproc。從sproc返回的數據返回IDictionary<string, object>ExpandoObject。這對於每個sproc的一個數據集來說工作得很好。現在我遇到了一個sproc,它在兩個不同的表中返回數據。當我打電話給我的功能時,我只能從第一個表中獲取數據。所以我的問題是我怎樣才能返回下一個數據集的數據。多個數據集ExpandoObject

注 - 我沒有改變存儲過程

我到目前爲止的代碼的權限是:

using(SqlDataReader reader = cmd.ExecuteReader()) 
{ 
    var names = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList(); 

    foreach (IDataRecord record in reader as IEnumerable) 
    { 
     IDictionary<string, object> expando = new ExpandoObject() as IDictionary<string, object>; 
     foreach (var name in names) 
     expando[name] = record[name]; 

     yield return expando; //yield return to keep the reader open 
    } 
} 
+0

我想我從來沒有見過從數據庫中讀取數據的這種奇怪的用法......你甚至稱'reader.Read()'? – lokusking

+0

你需要[SqlDataReader.NextResult](https://support.microsoft.com/en-us/kb/311274)嗎? – 2016-08-21 22:15:07

回答

3

乍看之下它看起來並不大的交易。使用ReadNextResult方法將foreach替換爲兩個嵌套循環,並將方法返回類型從IEnumerable<dynamic>更改爲IEnumerable<IEnumerable<dynamic>>(或IDictionary<string, object>而不是dynamic)。

但是,問題在於IEnumerable s是懶惰評估,並且DataReader是僅前向遊標,只能使用一次。

一種解決方案可能是在將內存中的每個結果(數據集)緩存到內存之前(例如使用List<dynamic>),然後將其返回給調用方,但這會消除延遲執行的好處。

而不是做緩衝,我建議你一種不同的方法 - 返回平坦結果集中的以下類型的方法:

public struct QueryResult 
{ 
    public readonly int Index; 
    public readonly dynamic Data; 
    internal QueryResult(int index, dynamic data) 
    { 
     Index = index; 
     Data = data; 
    } 
} 

其中Index字段將包含結果(數據集)的索引(0 ,1,2等)。使用foreach循環(一個或多個),LINQ GroupByMoreLINQGroupAdjacent

隨着該設計決策,例如實施很簡單 - 這將使用最適當的方式保持延遲執行的好處,並讓呼叫者過程中它:

static IEnumerable<QueryResult> GetData(SqlCommand command) 
{ 
    using (var reader = command.ExecuteReader()) 
    { 
     int index = 0; 
     do 
     { 
      while (reader.Read()) 
      { 
       IDictionary<string, object> expando = new ExpandoObject(); 
       for (int i = 0; i < reader.FieldCount; i++) 
        expando.Add(reader.GetName(i), reader.GetValue(i)); 
       yield return new QueryResult(index, expando); 
      } 
      index++; 
     } 
     while (reader.NextResult()); 
    } 
} 
+0

謝謝你的回答。我將如何調用GetData()方法?目前我實現爲'public IEnumerable GetDataFromSproc()',並將其稱爲IEnumerable dataList = helper.GetDataFromSproc()' – Code

+0

這取決於您在調用之後會做什麼。當有多個結果時,你會期望什麼?獲取列表的列表,或者手動構建單獨的列表還是?給我一些用例。 –

+0

當前如果有多個結果,那麼我會調用它兩次,並將它組合成一個列表。大部分返回數據的Sproc都會有一組。然而,有幾個(4-5)最多的結果集爲2或更多。所以我問了這個問題。在剃刀視圖中,我遍歷'List '並執行類似於@ Html.DisplayName((string)Model [i] .SomeValue)' – Code