2017-08-08 120 views
1

我正在執行存儲過程,使用QueryMultiple來返回多組數據。QueryMultiple Result Set Order Changed

var gridReader = db.QueryMultiple("sp", 
            parameters, 
            commandType: CommandType.StoredProcedure); 

我可以很輕鬆地獲得各組給予我知道訂單,他們會回去。

SELECT * FROM dbo.Set1; 
SELECT * FROM dbo.Set2; 
SELECT * FROM dbo.Set3; 
var set1 = gridReader.Read<Set1>(); 
var set2 = gridReader.Read<Set2>(); 
var set3 = gridReader.Read<Set3>(); 

不過,我在的情況下,他們的順序會回來可能會改變。另一位開發人員可能因爲任何原因決定更改訂單。存儲過程現在變爲:

SELECT * FROM dbo.Set1; 
SELECT * FROM dbo.Set3; 
SELECT * FROM dbo.Set2; 

我該如何處理?

我最初的嘗試是迭代每個網格,檢查列名稱。這似乎起初運作良好,但我無法弄清楚如何將網格投影到課程中,除了手動設置每個字段。我使用Dapper的主要原因是它可以爲我做到這一點。

while (true) 
{ 
    var grid = gridReader.Read(); 
    IDictionary<string, object> row = grid.FirstOrDefault(); 

    if (row == null) 
     break; 

    if (row.Keys.Contains("Set1_UniqueColumnName")) 
    { 
     // Need something like grid.Read<Set1>(); 
    } 
    else if (row.Keys.Contains("Set2_UniqueColumnName")) { } 
    else if (row.Keys.Contains("Set3_UniqueColumnName")) { } 
} 

我的第二個想法是讀每個網格成一個類,檢查類的唯一字段空值/默認值,並試圖在下次上課;如果測試失敗。這顯然不會工作。 .Read()將返回下一個網格的結果。這個解決方案需要我能夠一遍又一遍地讀取同一個網格。

回答

1

Davmos's answer指出我在正確的方向。需要使用ADO.NET和Dapper的組合。基本上使用ADO.NET來檢索和遍歷數據,但使用Dapper將行解析到我的對象中。注意在結果集實際上返回0行的情況下,在while循環中使用FieldCount。我們希望它移動到下一個結果集,而不是跳出循環。

Set1 set1 = null; 
var set2 = new List<Set2>(); 
Set3 set3 = null; 

using (var command = new SqlCommand("sp", conn)) 
{ 
    command.CommandType = CommandType.StoredProcedure; 
    command.Parameters.AddRange(parameters); 
    command.Connection.Open(); 

    using (var reader = command.ExecuteReader()) 
    { 
     while (reader.FieldCount > 0) 
     { 
      var set1Parser = reader.GetRowParser<Set1>(); 
      var set2Parser = reader.GetRowParser<Set2>(); 
      var set3Parser = reader.GetRowParser<Set3>(); 

      var isSet1 = HasColumn(reader, "Set1_UniqueColumnName"); 
      var isSet2 = HasColumn(reader, "Set2_UniqueColumnName"); 
      var isSet3 = HasColumn(reader, "Set3_UniqueColumnName"); 

      while (reader.Read()) 
      { 
       if (isSet1) 
       { 
        set1 = set1Parser(reader); 
       } 
       else if (isSet2) 
       { 
        set2.Add(set2Parser(reader)); 
       } 
       else if (isSet3) 
       { 
        set3 = set3Parser(reader); 
       } 
      } 

      reader.NextResult(); 
     } 
    } 
} 
public static bool HasColumn(IDataReader reader, string columnName) 
{ 
    for (var i = 0; i < reader.FieldCount; i++) 
    { 
     if (reader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase)) 
     { 
      return true; 
     } 
    } 

    return false; 
} 
2

Dapper提供了一個IDataReader.GetRowParser擴展方法,可以實現每行的類型切換。從小巧精緻的文檔here ...

通常你想從一個給定的表來對待所有行一樣 數據類型。但是,在某些情況下, 可以將不同的行解析爲不同的數據類型。這是IDataReader.GetRowParser派上用場的地方。

假設你有一個名爲「形狀」與列的數據庫表:ID, 類型和數據,並且要分析它的行成圓形,方形,或 三角物體基於該類型列的值。

​​

你需要獲得訪問IDataReaderGridReader包裝或更改代碼以使用老式的ADO.NET這樣SqlConnection & SqlCommand對象...

using (command = new SqlCommand("sp", connection)) 
{ 
    command.CommandType = CommandType.StoredProcedure; 
    command.Parameters.AddRange(parameters); 

    using (var reader = command.ExecuteReader()) 
    { 
     while (reader.HasRows) 
     { 
      while(reader.Read()) 
      { 

      } 

      reader.NextResult(); 
     } 
    } 
} 
+0

謝謝你指着我在正確的方向!我想我會需要'GetRowParser',但我無法弄清楚。將它與SqlDataReader結合起來就是個訣竅。 –

+0

不客氣:)幹得好! – davmos