2016-08-19 12 views
0

私は現在sprocを呼び出しています。 sprocから返されたデータは、IDictionary<string, object>ExpandoObjectを返しました。これは、sprocごとに1つのデータセットに対して完全に正常に機能します。今私はsprocに出くわしました。これは2つの異なるテーブルにデータを返します。関数を呼び出すと、最初のテーブルからデータが取得されます。だから私の質問は、次のデータセットのデータも返すことができます。ExpandoObjectに複数のデータセット

注 - 私はSPROCを

私がこれまで持っているコードを変更する権限を持っていないです:それは大したことを見ていない一見

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)が必要ですか? –

答えて

3

foreachReadおよびNextResultのメソッドを使用して2つのネストしたループに置き換え、メソッドの戻り値の型をIEnumerable<dynamic>からIEnumerable<IEnumerable<dynamic>>(またはdynamicの代わりにIDictionary<string, object>)に変更します。

しかし、問題はIEnumerableが遅れて評価され、DataReaderが順方向のカーソルであり、1回しか消費できないということです。

1つの解決策は、呼び出し元に返す前にすべての結果(データセット)をメモリにバッファリングすることです(たとえば、List<dynamic>を使用します)が、遅延実行のメリットはありません。 Indexフィールドは、結果が含まれます

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

(データセット)インデックス(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

現在、複数の結果がある場合は、2回呼び出して1つのリストにまとめます。データを返すSprocのほとんどは1つのセットを持つでしょう。しかし、2つ以上の結果セットを持つものが最も多いもの(4-5)があります。それでなぜ私は質問したのですか?そして、剃刀のビューでは、 'List 'をループし、 '@ Html.DisplayName((string)Model [i] .SomeValue)'のようにします。 – Code

関連する問題